Go语言学习笔记-Go语言结构体
Go语言结构体1. 结构体创建、访问与修改1.1 定义结构体1.2 声明和初始化结构体1.3 访问与修改结构体1.4 成员函数(方法)1.5 为自定义类型添加方法1.6 匿名结构体1.7 结构体中含有匿名成员 2. 结构体指针2.1 创建结构体指针2.2 方法接收指针 3. 结构体嵌套4. 深拷贝与浅拷贝Go语言结构体
1. 结构体创建、访问与修改
1.1 定义结构体
//定义user结构体type user struct {id intscore float32enrollment time.Timename, addr string //多个字段类型相同时可以简写到一行里}
1.2 声明和初始化结构体
var u user //声明,会用相应类型的默认值初始化struct里的每一个字段u = user{} //用相应类型的默认值初始化struct里的每一个字段u = user{id: 3, name: "xiaoming"} //赋值初始化u = user{4, 100.0, time.Now(), "xiaoming", "beijing"} //赋值初始化,可以不写字段名,但需要跟结构体定义里的字段顺序一致
1.3 访问与修改结构体
u.enrollment = time.Now() //给结构体的成员变量赋值fmt.Printf("id=%d, enrollment=%v, name=%s\n", u.id, u.enrollment, u.name)//访问结构体的成员变量
1.4 成员函数(方法)
//可以把user理解为hello函数的参数,即hello(u user, man string)func (u user) hello(man string) {fmt.Println("hi " + man + ", my name is " + u.name)}//函数里不需要访问user的成员,可以传匿名,甚至_也不传func (_ user) think(man string) {fmt.Println("hi " + man + ", do you know my name?")}
1.5 为自定义类型添加方法
type UserMap map[int]User //自定义类型//可以给自定义类型添加任意方法func (um UserMap) GetUser(id int) User {return um[id]}
结构体的可见性:
go语言关于可见的统一规则:大写字母开头跨package也可以访问;否则只能本package内部访问。结构体名称以大写开头时,package外部可见,在此前提下,结构体中以大写开头在成员变量或成员方法在package外部也可见。
1.6 匿名结构体
var stu struct { //声明stu是一个结构体,但这个结构体是匿名的Name stringAddr string}stu.Name = "zcy"stu.Addr = "bj"
匿名结构体通常用于只使用一次的情况。
1.7 结构体中含有匿名成员
type Student struct {Id intstring //匿名字段float32 //直接使用数据类型作为字段名,所以匿名字段中不能出现重复的数据类型}var stu = Student{Id: 1, string: "zcy", float32: 79.5}fmt.Printf("anonymous_member string member=%s float member=%f\n", stu.string, stu.float32) //直接使用数据类型访问匿名成员
2. 结构体指针
2.1 创建结构体指针
var u Useruser := &u //通过取址符&得到指针user = &User{ //直接创建结构体指针Id: 3, Name: "zcy", addr: "beijing",}user = new(User) //通过new()函数实体化一个结构体,并返回其指针
构造函数(go语言中实际是没有构造函数的)
//构造函数。返回指针是为了避免值拷贝func NewUser(id int, name string) *User {return &User{Id: id,Name: name,addr: "China",Score: 59,}}
2.2 方法接收指针
//user传的是值,即传的是整个结构体的拷贝。在函数里修改结构体不会影响原来的结构体func hello(u user, man string) {u.name = "杰克"fmt.Println("hi " + man + ", my name is " + u.name)}//传的是user指针,在函数里修改user的成员会影响原来的结构体func hello2(u *user, man string) {u.name = "杰克"fmt.Println("hi " + man + ", my name is " + u.name)}//把user理解为hello()的参数,即hello(u user, man string)func (u user) hello(man string) {u.name = "杰克"fmt.Println("hi " + man + ", my name is " + u.name)}//可以理解为hello2(u *user, man string)func (u *user) hello2(man string) {u.name = "杰克"fmt.Println("hi " + man + ", my name is " + u.name)}
3. 结构体嵌套
type user struct {name stringsex byte}type paper struct {name stringauther user //结构体嵌套}p := new(paper)p.name = "论文标题"p.auther.name = "作者姓名"p.auther.sex = 0type vedio struct {length intname stringuser//匿名字段,可用数据类型当字段名}
结构体嵌套时字段名冲突的问题
v := new(vedio)v.length = 13v.name = "视频名称"v.user.sex = 0 //通过字段名逐级访问v.sex = 0 //对于匿名字段也可以跳过中间字段名,直接访问内部的字段名v.user.name = "作者姓名" //由于内部、外部结构体都有name这个字段,名字冲突了,所以需要指定中间字段名
4. 深拷贝与浅拷贝
type User struct {Name string}type Vedio struct {Length intAuthor User}
Go语言里的赋值都会发生值拷贝。
type User struct {Name string}type Vedio struct {Length intAuthor *User}
深拷贝,拷贝的是值,比如Vedio.Length。浅拷贝,拷贝的是指针,比如Vedio.Author。深拷贝开辟了新的内存空间,修改操作不影响原先的内存。浅拷贝指向的还是原来的内存空间,修改操作直接作用在原内存空间上。
结构体slice传参
传slice,对sclice的3个字段进行了拷贝,拷贝的是底层数组的指针,所以修改底层数组的元素会反应到原数组上。
users := []User{{Name: "康熙"}}func update_users(users []User) {users[0].Name = "光绪"}
本次课程演示代码
//main.gopackage mainimport struct2 "week03/struct"//type User struct {//Name string//}////func update_users(users []*User) {//users[0].Name = "光绪"//}func main() {//struct2.Init_struct()//struct2.TestSelftype()//b := struct2.Bird{}//b.Walk()struct2.TestStructPoint()//users := []User{{Name: "康熙"}, {Name: "小明"}} //光绪//a := User{Name: "康熙"}//b := User{Name: "小明"}//users := []*User{&a, &b} //发生了拷贝//update_users(users)//fmt.Println(users[0].Name) //光绪//fmt.Println(a.Name) //康熙}//basic.gopackage struct2import "fmt"type student struct {Id intName, address string}func (_ student) Walk() {fmt.Println("runing")}type Bird struct{}func (Bird) Walk() {fmt.Println("fly")}func (a student) sing(man string) {fmt.Println("hello " + man + " " + a.address)}func Init_struct() {var a studentfmt.Printf("%d %s %s\n", a.Id, a.Name, a.address) //0a = student{}fmt.Printf("%d %s %s\n", a.Id, a.Name, a.address) //0a = student{Id: 4}fmt.Printf("%d %s %s\n", a.Id, a.Name, a.address) //4a.Id = 7a.Name = "xiaoming"fmt.Printf("%d %s %s\n", a.Id, a.Name, a.address) //7 xiaoming}type A struct {Id int}var ccc struct {Id intName string}func f() {var sss Afmt.Println(sss.Id)var ddd Afmt.Println(ddd.Id)fmt.Println(ccc.Id)}//sp.gopackage struct2import "fmt"func hello1(u student) {u.Id = 888fmt.Println(u.Id) //888}func hello2(u *student) {u.Id = 888fmt.Println(u.Id) //888}func (u student) hello1() {u.Id = 888fmt.Println(u.Id) //888}func (u *student) hello2() {u.Id = 888fmt.Println(u.Id) //888}func TestStructPoint() {var s student //s.Id=0//hello1(s)s.hello1()fmt.Println(s.Id) //0//hello2(&s)s.hello2()fmt.Println(s.Id) //888}//self_type.gopackage struct2import ("fmt")type AAA intfunc (AAA) Say() {fmt.Println("say")}func (AAA) Hello() {fmt.Println("hello")}func TestSelftype() {var v AAAv = 345fmt.Printf("%d\n", v)v.Say()v.Hello()}// 构造函数func NewStrudent(id int) *student {s := student{}s.Id = ids.address = "BJ"s.Name = "小张"return &s}func testConstruct() {a := NewStrudent(100)fmt.Println(a.address)}//父类type Animal struct {}//子类type Human struct {}// 匿名时候type Vedio struct {Name stringstudent}func TsetNest() {v := Vedio{Name: "tlbb"}v.student = student{Id: 123, Name: "jy", address: "sh"}fmt.Println(v.Name) //tlbbfmt.Println(v.student.Id) //123fmt.Println(v.Id) //Id和address本来是student成员,现在Vedio可以直接访问,即Vedio直接拥有了Id和address,形式上等价于Vedio继承了studentfmt.Println(v.address)//shfmt.Println(v.student.Name) //jy}// 不匿名时候//type Vedio struct {//Name string//s student//}////func TsetNest() {//v := Vedio{Name: "tlbb"}//v.s = student{Id: 123, Name: "jy", address: "sh"}//fmt.Println(v.Name)//tlbb//fmt.Println(v.s.Id)//123//fmt.Println(v.s.Id)//123//fmt.Println(v.s.address) //sh//fmt.Println(v.s.Name) //jy//}
如果觉得《Go语言学习笔记-Go语言结构体》对你有帮助,请点赞、收藏,并留下你的观点哦!