Go语言入门学习--基础篇

1.数据类型

1.1基础数据类型

布尔型 bool

整型 int

浮点型flaot32/64

字符型 byte

字符串 string

1.数据类型

1.1基础数据类型

布尔型 bool

整型 int

浮点型flaot32/64

字符型 byte

字符串 string

//基础数据类型

  //定义一个布尔类型的变量a

  var a bool

  //定义一个int类型的变量b

  var b int

  //float32类型

  var c float32

  //字符类型

  var d byte

  //字符串

  var e string

 

1.2派生类型

指针类型(pointer)

数组类型

结构化类型(struct)

Channel 类型

函数类型

切片类型

接口类型(interface)

Map 类型

//定义一个长度为2的string数组f

  var f [2]string

  

  //定义一个切片g 切片类似于list的结构

  var g []int

  

  //定义一个结构体h 结构体类似于Java中的entity的概念 但是使用更加灵活

  type h struct {

   x string

   y int

   z float32

  }

  

  //定义一个Map i,示例中 string为map的key类型,int为map的value类型

  var i map[string[LL(1] ]int[LL(2] 

  

  //指针类型 j是一个指向int值的指针

  var j *int
//定义一个main方法,main方法为一个项目的主方法 

func main()  {
//定义并赋值l,使用 := ,l的类型为所赋值的类型

 l:=1
// &l代表指向l变量的内存地址

 j=&l
// 在指针j前面加*用来获取指针j所指向的内容

 m :=*j

 fmt.Print(j,m)[LL(3] 

}
// 创建一个传递string类型的信道n
var n chan  string

上述main函数运行结果如下

0xc00000a0c8 1

Interface和channel使用在后面单独章节

2.流程控制

2.1 for

类似于其他语言,for循环有三种形式,Break 关键字可以用于跳出循环

//for 初始化条件; 循环控制条件; 赋值表达式 {循环体}

  for i := 0; i < 5; i++[LL(4]  {

   fmt.Println(i)

}
  m := 5

  n := 0

  //for 循环控制条件{循环体}

  for n < m {

   n++

   fmt.Println(n)

}

  //for range 用于遍历数组,切片,map 格式如下

  // for index/key,value :=range slice/map/数组 {fmt.Print(index/key,value)}

  x := []int{1, 2, 1, 5, 10}

  for y, z := range x {

   fmt.Printf("第 %d 位 x 的值 = %d\n", y, z)

}

 

运行结果如下

//第一个for循环运行结果

0

1

2

3

4

//第二个for循环运行结果

1

2

3

4

5

//第三个for循环运行结果

第 0 位 x 的值 = 1

第 1 位 x 的值 = 2

第 2 位 x 的值 = 1

第 3 位 x 的值 = 5

第 4 位 x 的值 = 10

2.2 if

m := 5

  n := 0

  //if 布尔表达式{
表达式为true时执行的语句
//}else{ else必须和if结束的大括号同一行
}

  if n < m {

   fmt.Println(n)

}else{

     fmt.Println(m)

}

 

If语句可以嵌套

2.3 swich

grade := ""

  marks := 90

  switch marks {

  case 90[LL(5] :

   grade = "A"

  case 80:

   grade = "B"

  case 50, 60, 70:

   grade = "C"
//default表示如果没有匹配到case 则执行default内表达式

  default:

   grade = "D"

  }

  fmt.Print(grade)

 

3.函数与方法

3.1函数与方法的定义

在很多语言中,函数和方法指的是同一种东西。但是在Go语言中有所区别

在 Go 语言中有一个概念和函数极其相似,叫做方法 。Go 语言的方法其实是作用在接收者(receiver)上的一个函数,接收者是某种非内置类型的变量。因此方法是一种特殊类型的函数。

 

//定义一个结构体student
type student struct {

   Id   int

   Name string

  }

  //定义一个函数getName() 返回值类型为string

  func getName[LL(6] (stu student) string {
   fmt.Println("函数被调用")

   return stu.Name

  }

  //定义一个方法 getName

  func (stu student) getName() string {
   fmt.Println("方法被调用")

   return stu.Name

  }

 

3.2函数和方法的调用

函数将变量作为参数:Function1(recv)

方法在变量上被调用:recv.Method1()

func main() {

   a := student{

      Id:   12,

      Name: "Any",

   }[LL(7] 
//调用getName()函数

   getName(a)
//调用getName()方法

   a.getName()

}

 

运行结果如下

函数被调用

方法被调用

 

4.接口

4.1定义一个接口

Go 语言并没有类和继承的概念。但是 Go 语言里有非常灵活的接口概念,通过它可以实现很多面向对象的特性。接口定义了一组方法集合,但是这些方法不包含具体的实现代码,接口定义中不能包含变量。

//使用interface关键字定义接口,Phone为接口名,call()为接口中定义的方法
type Phone interface {

   call()

   //message()

  }

4.2实现接口

实现一个接口需要实现接口中的所有方法。

type Nokia struct {

   name  string

   model string

  }

  type Iphone struct {

   name string

   color string

  }

  //

  func (nokia Nokia)call()  {

   fmt.Printf("nokia call ! %v ,%v",nokia.name,nokia.model)

}

  func (iphone Iphone)call()  {

   fmt.Printf("iPhone call! %v,%v",iphone.name,iphone.color)

}

 

4.3使用接口

func main() {

   /* var phone Phone

      phone = Nokia{

         name:  "机皇",

         model: "N97",

      }

      fmt.Println(reflect.TypeOf(phone))

      phone.call()*/

   phone := Nokia{

      name:  "机皇",

      model: "N97",

   }

   phone.call()

  

   iphone := Iphone{

      name:  "5s",

      color: "rich gold",

   }

   iphone.call()

}

 

4.4接口嵌套

接口可以嵌套,子接口拥有父接口所有方法,使用子接口时,需要实现父接口和子接口中所有的方法。

type Phone interface {

   Call

   Message

  }

  type Call interface {

   answer()

}

  type Message interface {

   sendMessage()

   receiceMessage()

}

 

4.5空接口

Go语言空接口(interface{})不包含任何的method,所有的类型都实现了空interface,空interface可以存储任意类型的数值。[LL(8] 

slice := make([]interface{}, 10)

  map1 := make(map[string]string)

  map2 := make(map[string]int)

  map2["TaskID"] = 1

  map1["Command"] = "ping"

  map3 := make(map[string]map[string]string)

  map3["mapvalue"] = map1

slice[0] = map2

slice[1] = map1

slice[3] = map3

  fmt.Println(slice[0])

  fmt.Println(slice[1])

  fmt.Println(slice[3])

 

5.反射[LL(9] 

反射需要用到reflect包

5.1利用反射获取数据类型和值

reflect.ValueOf()用于获取参数的值,获取的参数类型为空接口,可以获取所有类型的参数

reflect.TypeOf()用于获取参数的类型

var circle float64 = 6.28[LL(10] 

  fmt.Println("Reflect : circle.Value = ", reflect.ValueOf(circle))

  fmt.Println("Reflect : circle.Type  = ", reflect.TypeOf(circle))

 

5.2用反射进行变量修改

var circle float64 = 6.28

  //CanSet()函数确认变量是否是可修改的

  value := reflect.ValueOf(circle)

  fmt.Println("Reflect : value = ", value)

  fmt.Println("Settability of value : ", value.CanSet())

  //value2表示指向circle的指针

  value2 := reflect.ValueOf(&circle)

  fmt.Println("Settability of value : ", value2.CanSet())

  //value3是表示circle的指针的反射   reflect.Elem() 获取这个指针指向的元素类型

  value3 := value2.Elem()

  fmt.Println("Settability of value : ", value3.CanSet())

  //修改circle的指针的反射类型的值

  value3.SetFloat(3.14)

  fmt.Println("Value of value3: ", value3)

  fmt.Println("value of circle: ", circle)

 

 

6.并发

6.1 goroutine(协程)

在Go中,应用程序并发处理的部分被称作 goroutines(go协程),它可以进行更有效的并发运算。在协程和操作系统线程之间并无一对一的关系:协程是根据一个或多个线程的可用性,映射(多路复用,执行于)在它们之上的;协程调度器在 Go 运行时很好的完成了这个工作。

Go 程序中使用 go 关键字为一个函数创建一个 goroutine。一个函数可以被创建多个 goroutine,一个 goroutine 必定对应一个函数。

func main() {
//创建一个loop方法的协程

   go loop()

   loop()

  

}

  func loop() {

   for i := 0; i < 10; i++ {

      fmt.Printf("%d ", i)

   }

}

 

6.2 channel(信道)

Channel是Go中的一个核心类型,可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯。

它的操作符是箭头 <-

var x bool

  c := make(chan bool) //创建一个无缓冲的bool型Channel

  c <- x        //向一个Channel发送一个值x

  <- c          //从一个Channel中接收一个值

  x = <- c      //从Channel c接收一个值并将其存储到x中

  x, ok = <- c  //从Channel接收一个值,如果channel关闭了或没有数据,那么ok将被置为false

 

信道在取消息和存消息的时候都会挂起当前的goroutine,除非另一端已经准备好。如果不用信道来阻塞主线的话,主线程就会过早跑完,loop线程都没有机会执行。

var complete := make(chan int)[LL(11] 

  

  func loop() {

   for i := 0; i < 10; i++ {

      fmt.Printf("%d ", i)

   }

   complete <- 0 // 执行完毕了,发出消息

  }

  

  func main() {

   go loop()

   <-complete // 直到线程跑完, 取到消息. main在此阻塞住

  }

 

 

7.错误和异常处理

7.1 error(错误)

一般情况下,如果函数需要返回错误,就将 error 作为多个返回值中的最后一个(但并非是强制要求)。

func Sqrt(f float64) (float64, error) {

   if f < 0 {

      return -1, errors.New("参数必须不小于0")

   }
// 执行开方计算

   return math.Sqrt(f) , nil

  }

  

  func main(){

   result, err:= Sqrt(-2)

   if err != nil   {

      fmt.Println(err)

   }else{

      fmt.Println(result)

   }

}

 

7.2 panic(异常)

错误指的是可能出现问题的地方出现了问题,比如打开一个文件时失败,这种情况在人们的意料之中 ;而异常指的是不应该出现问题的地方出现了问题,比如引用了空指针,这种情况在人们的意料之外。错误是业务过程的一部分,而异常不是 。

func main() {

   fmt.Println("Starting the program")

   panic("A severe error occurred: stopping the program!")

   fmt.Println("Ending the program")

}

 

recover是一个内建的函数,可以让进入令人恐慌的流程中的goroutine恢复过来。recover仅在延迟函数中有效。在正常的执行过程中,调用recover会返回nil,并且没有其它任何效果。如果当前的goroutine陷入panic,调用recover可以捕获到panic的输入值,并且恢复正常的执行。[LL(12] 

 

可以使用关键字defer向函数注册退出调用,即主调函数退出时,defer后的函数才会被调用。

defer语句的作用是不管程序是否出现异常,均在函数退出时自动执行相关代码(类似于Java中的finally)。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。

func badCall() {

   panic("bad end")

}

  

  func test() {

   defer func() {

      if e := recover(); e != nil {

         fmt.Printf("Panicing %s\n", e)

      }

   }()

   badCall()

   fmt.Printf("After bad call\n")

}

  

  func main() {

   fmt.Printf("Calling test\n")

   test()

   fmt.Printf("Test completed\n")

}

 

 


 [LL(1]stringmapkey类型

 [LL(2]intmapvalue类型

 [LL(3]使用Print函数日志输出

 [LL(4]Go语言中自增i++不是一个操作符而是语句,所以i=i++会导致编译错误,不存在++i,--也一样

 [LL(5]case 90 [LL(5]表示marks==90是否成立,若结果为true则执行下面的 grade = "A",若不成立则执行下一个case

 [LL(6]在同一个package下允许函数和方法同名,但不允许函数之间同名。

Go语言中允许方法同名,但不允许同名方法同参,类似于Java中方法重载的概念

 [LL(7]声明一个结构体变量a

 [LL(8]类似于Java中的Object。

 [LL(9]反射机制也类似于Java,其中reflect包功能类似于.Class

 [LL(10]这里是我们已经定义的一个值,但是反射机制可以让我们获取空接口传来的任意参数的类型和值

 

 [LL(11]创建一个无缓冲的int型 channel

 [LL(12]类似于Java中的try catch模块

 

1.2派生类型

指针类型(pointer)

数组类型

结构化类型(struct)

Channel 类型

函数类型

切片类型

接口类型(interface)

Map 类型

//定义一个长度为2的string数组f

  var f [2]string

  

  //定义一个切片g 切片类似于list的结构

  var g []int

  

  //定义一个结构体h 结构体类似于Java中的entity的概念 但是使用更加灵活

  type h struct {

   x string

   y int

   z float32

  }

  

  //定义一个Map i,示例中 string为map的key类型,int为map的value类型

  var i map[string[LL(1] ]int[LL(2] 

  

  //指针类型 j是一个指向int值的指针

  var j *int
//定义一个main方法,main方法为一个项目的主方法 

func main()  {
//定义并赋值l,使用 := ,l的类型为所赋值的类型

 l:=1
// &l代表指向l变量的内存地址

 j=&l
// 在指针j前面加*用来获取指针j所指向的内容

 m :=*j

 fmt.Print(j,m)[LL(3] 

}
// 创建一个传递string类型的信道n
var n chan  string

上述main函数运行结果如下

0xc00000a0c8 1

Interface和channel使用在后面单独章节

2.流程控制

2.1 for

类似于其他语言,for循环有三种形式,Break 关键字可以用于跳出循环

//for 初始化条件; 循环控制条件; 赋值表达式 {循环体}

  for i := 0; i < 5; i++[LL(4]  {

   fmt.Println(i)

}
  m := 5

  n := 0

  //for 循环控制条件{循环体}

  for n < m {

   n++

   fmt.Println(n)

}

  //for range 用于遍历数组,切片,map 格式如下

  // for index/key,value :=range slice/map/数组 {fmt.Print(index/key,value)}

  x := []int{1, 2, 1, 5, 10}

  for y, z := range x {

   fmt.Printf("第 %d 位 x 的值 = %d\n", y, z)

}

 

运行结果如下

//第一个for循环运行结果

0

1

2

3

4

//第二个for循环运行结果

1

2

3

4

5

//第三个for循环运行结果

第 0 位 x 的值 = 1

第 1 位 x 的值 = 2

第 2 位 x 的值 = 1

第 3 位 x 的值 = 5

第 4 位 x 的值 = 10

2.2 if

m := 5

  n := 0

  //if 布尔表达式{
表达式为true时执行的语句
//}else{ else必须和if结束的大括号同一行
}

  if n < m {

   fmt.Println(n)

}else{

     fmt.Println(m)

}

 

If语句可以嵌套

2.3 swich

grade := ""

  marks := 90

  switch marks {

  case 90[LL(5] :

   grade = "A"

  case 80:

   grade = "B"

  case 50, 60, 70:

   grade = "C"
//default表示如果没有匹配到case 则执行default内表达式

  default:

   grade = "D"

  }

  fmt.Print(grade)

 

3.函数与方法

3.1函数与方法的定义

在很多语言中,函数和方法指的是同一种东西。但是在Go语言中有所区别

在 Go 语言中有一个概念和函数极其相似,叫做方法 。Go 语言的方法其实是作用在接收者(receiver)上的一个函数,接收者是某种非内置类型的变量。因此方法是一种特殊类型的函数。

 

//定义一个结构体student
type student struct {

   Id   int

   Name string

  }

  //定义一个函数getName() 返回值类型为string

  func getName[LL(6] (stu student) string {
   fmt.Println("函数被调用")

   return stu.Name

  }

  //定义一个方法 getName

  func (stu student) getName() string {
   fmt.Println("方法被调用")

   return stu.Name

  }

 

3.2函数和方法的调用

函数将变量作为参数:Function1(recv)

方法在变量上被调用:recv.Method1()

func main() {

   a := student{

      Id:   12,

      Name: "Any",

   }[LL(7] 
//调用getName()函数

   getName(a)
//调用getName()方法

   a.getName()

}

 

运行结果如下

函数被调用

方法被调用

 

4.接口

4.1定义一个接口

Go 语言并没有类和继承的概念。但是 Go 语言里有非常灵活的接口概念,通过它可以实现很多面向对象的特性。接口定义了一组方法集合,但是这些方法不包含具体的实现代码,接口定义中不能包含变量。

//使用interface关键字定义接口,Phone为接口名,call()为接口中定义的方法
type Phone interface {

   call()

   //message()

  }

4.2实现接口

实现一个接口需要实现接口中的所有方法。

type Nokia struct {

   name  string

   model string

  }

  type Iphone struct {

   name string

   color string

  }

  //

  func (nokia Nokia)call()  {

   fmt.Printf("nokia call ! %v ,%v",nokia.name,nokia.model)

}

  func (iphone Iphone)call()  {

   fmt.Printf("iPhone call! %v,%v",iphone.name,iphone.color)

}

 

4.3使用接口

func main() {

   /* var phone Phone

      phone = Nokia{

         name:  "机皇",

         model: "N97",

      }

      fmt.Println(reflect.TypeOf(phone))

      phone.call()*/

   phone := Nokia{

      name:  "机皇",

      model: "N97",

   }

   phone.call()

  

   iphone := Iphone{

      name:  "5s",

      color: "rich gold",

   }

   iphone.call()

}

 

4.4接口嵌套

接口可以嵌套,子接口拥有父接口所有方法,使用子接口时,需要实现父接口和子接口中所有的方法。

type Phone interface {

   Call

   Message

  }

  type Call interface {

   answer()

}

  type Message interface {

   sendMessage()

   receiceMessage()

}

 

4.5空接口

Go语言空接口(interface{})不包含任何的method,所有的类型都实现了空interface,空interface可以存储任意类型的数值。[LL(8] 

slice := make([]interface{}, 10)

  map1 := make(map[string]string)

  map2 := make(map[string]int)

  map2["TaskID"] = 1

  map1["Command"] = "ping"

  map3 := make(map[string]map[string]string)

  map3["mapvalue"] = map1

slice[0] = map2

slice[1] = map1

slice[3] = map3

  fmt.Println(slice[0])

  fmt.Println(slice[1])

  fmt.Println(slice[3])

 

5.反射[LL(9] 

反射需要用到reflect包

5.1利用反射获取数据类型和值

reflect.ValueOf()用于获取参数的值,获取的参数类型为空接口,可以获取所有类型的参数

reflect.TypeOf()用于获取参数的类型

var circle float64 = 6.28[LL(10] 

  fmt.Println("Reflect : circle.Value = ", reflect.ValueOf(circle))

  fmt.Println("Reflect : circle.Type  = ", reflect.TypeOf(circle))

 

5.2用反射进行变量修改

var circle float64 = 6.28

  //CanSet()函数确认变量是否是可修改的

  value := reflect.ValueOf(circle)

  fmt.Println("Reflect : value = ", value)

  fmt.Println("Settability of value : ", value.CanSet())

  //value2表示指向circle的指针

  value2 := reflect.ValueOf(&circle)

  fmt.Println("Settability of value : ", value2.CanSet())

  //value3是表示circle的指针的反射   reflect.Elem() 获取这个指针指向的元素类型

  value3 := value2.Elem()

  fmt.Println("Settability of value : ", value3.CanSet())

  //修改circle的指针的反射类型的值

  value3.SetFloat(3.14)

  fmt.Println("Value of value3: ", value3)

  fmt.Println("value of circle: ", circle)

 

 

6.并发

6.1 goroutine(协程)

在Go中,应用程序并发处理的部分被称作 goroutines(go协程),它可以进行更有效的并发运算。在协程和操作系统线程之间并无一对一的关系:协程是根据一个或多个线程的可用性,映射(多路复用,执行于)在它们之上的;协程调度器在 Go 运行时很好的完成了这个工作。

Go 程序中使用 go 关键字为一个函数创建一个 goroutine。一个函数可以被创建多个 goroutine,一个 goroutine 必定对应一个函数。

func main() {
//创建一个loop方法的协程

   go loop()

   loop()

  

}

  func loop() {

   for i := 0; i < 10; i++ {

      fmt.Printf("%d ", i)

   }

}

 

 

 

 
  

 

Main()程序入口

 
  

 

 

 

 

                                               go running()

 

                                                       

 

                                                running()                                              running()

 

 

 

 

                                               主程序执行完毕

 

 

6.2 channel(信道)

Channel是Go中的一个核心类型,可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯。

它的操作符是箭头 <-

var x bool

  c := make(chan bool) //创建一个无缓冲的bool型Channel

  c <- x        //向一个Channel发送一个值x

  <- c          //从一个Channel中接收一个值

  x = <- c      //从Channel c接收一个值并将其存储到x中

  x, ok = <- c  //从Channel接收一个值,如果channel关闭了或没有数据,那么ok将被置为false

 

信道在取消息和存消息的时候都会挂起当前的goroutine,除非另一端已经准备好。如果不用信道来阻塞主线的话,主线程就会过早跑完,loop线程都没有机会执行。

var complete := make(chan int)[LL(11] 

  

  func loop() {

   for i := 0; i < 10; i++ {

      fmt.Printf("%d ", i)

   }

   complete <- 0 // 执行完毕了,发出消息

  }

  

  func main() {

   go loop()

   <-complete // 直到线程跑完, 取到消息. main在此阻塞住

  }

 

 

7.错误和异常处理

7.1 error(错误)

一般情况下,如果函数需要返回错误,就将 error 作为多个返回值中的最后一个(但并非是强制要求)。

func Sqrt(f float64) (float64, error) {

   if f < 0 {

      return -1, errors.New("参数必须不小于0")

   }
// 执行开方计算

   return math.Sqrt(f) , nil

  }

  

  func main(){

   result, err:= Sqrt(-2)

   if err != nil   {

      fmt.Println(err)

   }else{

      fmt.Println(result)

   }

}

 

7.2 panic(异常)

错误指的是可能出现问题的地方出现了问题,比如打开一个文件时失败,这种情况在人们的意料之中 ;而异常指的是不应该出现问题的地方出现了问题,比如引用了空指针,这种情况在人们的意料之外。错误是业务过程的一部分,而异常不是 。

func main() {

   fmt.Println("Starting the program")

   panic("A severe error occurred: stopping the program!")

   fmt.Println("Ending the program")

}

 

recover是一个内建的函数,可以让进入令人恐慌的流程中的goroutine恢复过来。recover仅在延迟函数中有效。在正常的执行过程中,调用recover会返回nil,并且没有其它任何效果。如果当前的goroutine陷入panic,调用recover可以捕获到panic的输入值,并且恢复正常的执行。[LL(12] 

 

可以使用关键字defer向函数注册退出调用,即主调函数退出时,defer后的函数才会被调用。

defer语句的作用是不管程序是否出现异常,均在函数退出时自动执行相关代码(类似于Java中的finally)。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。

func badCall() {

   panic("bad end")

}

  

  func test() {

   defer func() {

      if e := recover(); e != nil {

         fmt.Printf("Panicing %s\n", e)

      }

   }()

   badCall()

   fmt.Printf("After bad call\n")

}

  

  func main() {

   fmt.Printf("Calling test\n")

   test()

   fmt.Printf("Test completed\n")

}

 

 


 [LL(1]stringmapkey类型

 [LL(2]intmapvalue类型

 [LL(3]使用Print函数日志输出

 [LL(4]Go语言中自增i++不是一个操作符而是语句,所以i=i++会导致编译错误,不存在++i,--也一样

 [LL(5]case 90 [LL(5]表示marks==90是否成立,若结果为true则执行下面的 grade = "A",若不成立则执行下一个case

 [LL(6]在同一个package下允许函数和方法同名,但不允许函数之间同名。

Go语言中允许方法同名,但不允许同名方法同参,类似于Java中方法重载的概念

 [LL(7]声明一个结构体变量a

 [LL(8]类似于Java中的Object。

 [LL(9]反射机制也类似于Java,其中reflect包功能类似于.Class

 [LL(10]这里是我们已经定义的一个值,但是反射机制可以让我们获取空接口传来的任意参数的类型和值

 [LL(11]创建一个无缓冲的int型 channel

 [LL(12]类似于Java中的try catch模块

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值