结构体定义
定义结构体和C语言一样,使用struct关键字。在结构体内部定义它们的成员变量和类型,只是类型要放到后面,并且变量之间不用逗号。如果成员变量的类型相同的话,可以把它们写到同一行。
type Student struct {
name string
age int
weight float32
score []int
}
结构体初始化
可以变量初始化和指针初始化,代码如下:
package main
import (
"fmt"
)
type Student struct {
name string
age int
weight float32
score []int
}
func main() {
stu01 := Student{"qixuxiang", 23, 55.5, []int{95, 96, 98}} //按照字段顺序进行初始化
stu02 := Student{age: 23, weight: 55.5, score: []int{97, 98}, name: "sb"} //通过 field:value 形式初始化,该方式可以自定义初始化字段的顺序
var ptu1 = &Student{"qishuangzhu", 23, 55.0, []int{2, 3, 6, 4, 5, 9}} //初始化得到对象指针
pp := new(Student) //使用 new 关键字创建一个指针
*pp = Student{"qishuangming", 23, 65.0, []int{2, 3, 6}}
fmt.Printf("stu01.age is %d\n", stu01.age)
fmt.Printf("stu02 have %d subjects\n", len(stu02.score))
fmt.Printf("stu03's weight is %f\n", (*ptu1).weight)
fmt.Printf("stu03's weight is %f\n", ptu1.weight) //Go语言自带隐式解引用
fmt.Printf("stu pp have %d subjects\n", len((*pp).score))
fmt.Printf("stu pp have %d subjects\n", len(pp.score)) //Go语言自带隐式解引用
fmt.Printf("stu01 info is %#v\n", stu01) //结构体可以直接打印
}
Go语言指针
在Go语言中,直接砍掉了C语言指针最复杂的指针运算部分,只留下了获取指针(&运算符)和获取对象(*运算符)的运算,使用方法和C语言很类似。但不同的是,Go语言中没有 -> 操作符来调用指针所属的成员,而与一般对象一样,都是使用 . 来调用
Go语言自带指针隐式解引用 :对于一些复杂类型的指针, 如果要访问成员变量时候需要写成类似 *p.field的形式时,只需要p.field即可访问相应的成员。
示例代码见上面代码的后四行。
值类型和指针类型区别
对于一个函数(或方法),如果函数的参数(或接收者)是对象指针时,表示此对象是可被修改的;相反的,如果是对象时,表示是不可修改的(但如果该对象本身就是引用类型,如 map\func\chan 等,则本质上是可以修改的)。所以一般的做法是,方法的接收者习惯性使用对象指针,而不是对象,一方面可以在想修改对象时进行修改,另一方面也减少参数传递的拷贝成本。
另外,有一点尤为特殊,如果是作为函数的参数,则函数定义时,是使用对象还是对象指针,是有本质区别的,在使用对象作为参数的函数中,不能传入对象指针,同样的,在使用对象指针作为参数的函数中,也不能传入对象,否则编译器会报错。但如果是方法,则接收者定义为对象还是对象指针,都可以接收对象和对象指针的调用。下面我们来定义相关的函数和方法如下:
package main
import "fmt"
type Player struct{
userid int
username string
}
//传入 Player 对象参数
func print_obj(player Player) {
//player.username = "new" //修改并不会影响传入的对象本身
fmt.Println("userid:", player.userid)
}
//传入 Player 对象指针参数
func print_ptr(player *Player){
player.username = "new01"
fmt.Printf("userid is %d\n",player.userid)
fmt.Printf("username is %s\n",player.username)
}
//接收者为 Player 对象的方法,方法接收者的变量,按照 GO 语言的习惯一般不用 this/self ,而是使用接收者类型的第一个小写字母,可以看标准库中的代码风格。
func (p Player) m_print_obj(){
//p.username = "new02" 修改并不会影响传入的对象本身
fmt.Printf("userid is %d\n",p.userid)
}
//接收者为 Player 对象指针的方法
func (p *Player) m_print_ptr(){
p.username = "new03"
fmt.Printf("userid is %d\n",p.userid)
fmt.Printf("username is %s\n",p.username)
}
func main(){
player01 := Player{12 ,"test"}
pp := &Player {15 ,"newname"}
print_obj(player01)
print_ptr(pp)
player01.m_print_obj()
pp.m_print_ptr()
}