结构体
结构体是由一些列属性组成的复合数据类型,下面是一个简单的列子
package main import "fmt" type Counter int type User map[string]string func main() { var counter Counter = 20 counter += 10 fmt.Println(counter) //30 me := make(User) me["username"] = "zhangsan" me["age"] = "30" fmt.Println(me) //map[age:30 username:zhangsan] fmt.Printf("%T ,%T \n", counter, me) var callback = func(args ...string) { for i, v := range args { fmt.Println(i, ":", v) } } callback("a", "a", "c") var counter2 int = 10 fmt.Println(int(counter2) > counter2) }
结构体的定义
package main import "fmt" type User struct { ID int userName string age int Addr string remark string tel string } func main() { var user User fmt.Printf("%T \n", user) // main.User fmt.Printf("%#v\n", user) //main.User{ID:0, userName:"", age:0, Addr:"", remark:"", tel:""} var me2 = User{1, "张三", 10, "有道", "kwkw ", "182123455"} fmt.Printf("%#v\n", me2) //main.User{ID:1, userName:"张三", age:10, Addr:"有道", remark:"kwkw ", tel:"182123455"} var me3 = User{} fmt.Printf("%#v\n", me3) //指定属性名 var me4 User = User{ID: 1, userName: "zhangsan", age: 10, Addr: "海南省", remark: "张", tel: "1845"} fmt.Printf("%#v\n", me4) //main.User{ID:1, userName:"zhangsan", age:10, Addr:"海南省", remark:"张", tel:"1845"} fmt.Printf("%T \n",&me3) //*main.User 是一个指针类型 var pointer *User fmt.Printf("%T \n",pointer) fmt.Printf("%#v \n",pointer) var point2 *User = &me2 fmt.Printf("%#v \n",point2) var point3 *User = &User {} fmt.Printf("%#v \n",point3) //创建结构条的指针的时候,用new var pointer4 *User = new (User) fmt.Printf("%#v\n",pointer4) }
结构体的使用
package main import "fmt" type MyUser struct { ID int userName string age int Addr string remark string tel string } func main() { me := MyUser{ userName: "kk", ID: 1, Addr: "西安", } fmt.Println(me) me.tel = "182898329839" fmt.Printf("%#v\n", me) me2 := &MyUser{ ID: 2, userName: "wuha", } fmt.Printf("%T \n", me2) (*me2).tel = "18389389238" fmt.Printf("%#v\n", me2) me2.Addr = "北京 " fmt.Printf("%#v\n", me2) }
匿名结构体
package main import "fmt" func main() { var me struct { id int name string } fmt.Printf("%#v\n", me) // struct { id int; name string }{id:0, name:""} me2 := struct { Id int name string }{1, "2"} fmt.Printf("%#v \n", me2) // struct { Id int; name string }{Id:1, name:"2"} }
结构体中有另外的结构体
package main import "fmt" type Address struct { Region string Streect string No string } type User struct { Id int Name string Addr Address } func main() { var me01 User fmt.Printf("%#v \n", me01) //main.User{Id:0, Name:"", Addr:main.Address{Region:"", Streect:"", No:""}} user := User{ Id: 1, Name: "zhangsan", Addr: Address{ Region: "北京", Streect: "天水街道", No: "002", }, } fmt.Printf("%#v \n", user) //main.User{Id:1, Name:"zhangsan", Addr:main.Address{Region:"北京", Streect:"和", No:"002"}} fmt.Println(user.Addr.Streect) //天水街道 }
匿名嵌入
package main import "fmt" type Address struct { Region string Streect string No string } type User struct { Id int Name string Addr Address } type Employee struct { User Salary float64 } func main() { var me Employee fmt.Printf("%T,%#v", me, me)//main.Employee,main.Employee{User:main.User{Id:0, Name:"", Addr:main.Address{Region:"", Streect:"", No:""}}, Salary:0} }
指针结构体
package main import "fmt" type Address struct { Region string Streect string No string } type User struct { Id int Name string Addr *Address } type Employee1 struct { *User Salary float64 Name string } func main() { var me01 User fmt.Printf("%#v \n", me01) me02 := User{ Id: 1, Name: "kk", Addr: &Address{ "西安市", "大山", "大模大样", }, } fmt.Printf("%#v\n", me02) //main.User{Id:1, Name:"kk", Addr:(*main.Address)(0xc00006e180)} fmt.Println(me02.Addr.Streect) //大山 me02.Addr.Region = "北京市" fmt.Printf("%#v\n", me02.Addr) //&main.Address{Region:"北京市", Streect:"大山", No:"大模大样"} me03 := Employee1{ User: &User{ Id: 1, Name: "kk", Addr: &Address{ "西安", "业路", "iodis", }, }, } fmt.Println(me03.Addr.Streect) //业路 user1 := User{} user2 := user1 user2.Name = "张三" fmt.Printf("%#v\n", user1) //main.User{Id:0, Name:"", Addr:(*main.Address)(nil)} fmt.Printf("%#v\n", user2) //main.User{Id:0, Name:"张三", Addr:(*main.Address)(nil)} 按值类型传递 change(user1) fmt.Printf("%#v\n", user1) //main.User{Id:0, Name:"", Addr:(*main.Address)(nil)} 按值类型传递 changePoint(&user1) fmt.Printf("%#v\n", user1) //main.User{Id:0, Name:"yyyyyyy", Addr:(*main.Address)(nil)} 按地址传递 mex := User{ Id: 1 , Name: "kk ", Addr: &Address{"西安","锦业","001"}, } mex2 := mex fmt.Println(mex2.Name) // // fmt.Println(mex2.Addr.Streect ) //如果没有初始化 的话 panic: runtime error: invalid memory address or nil pointer dereference } func change(u User) { u.Name = "xxxxxx" } func changePoint(u * User ){ u.Name = "yyyyyyy" }
创建新用户
package main import ( "fmt" ) type Address struct { Region string Streect string No string } type User struct { Id int Name string Addr Address } func NewUser(id int, name string, region string) User { return User{ Id: id, Name: name, Addr: Address{ Region: region, }, } } func main() { me := User{} me2 := me me2.Name = "kk" fmt.Printf("%#v\n", me) //值类型 fmt.Printf("%#v\n", me2) user := NewUser(1,"iodsoi","83ew98") fmt.Printf("%#v\n",user) //main.User{Id:1, Name:"iodsoi", Addr:main.Address{Region:"83ew98", Streect:"", No:""}} } package main import "fmt" type Dog struct { Name string } func (dog Dog) Call(){ fmt.Printf("%s :汪汪",dog.Name) } func main() { dog := Dog{"豆豆"} dog.Call() //豆豆 :汪汪 }
package main import "fmt" type Address struct { Region string Street string No string } func (addr Address) Addr() string { return fmt.Sprintf("%s-%s-%s ", addr.Region, addr.Street, addr.No) } type User struct { ID int Name string Addr Address } func (user User) User() string { return fmt.Sprintf("[%d]%s:%s", user.ID, user.Name, user.Addr) } func (user User) String() string { return fmt.Sprintf("[%d]%s:%s", user.ID, user.Name, user.Addr) } func main() { var u User = User{ ID: 1, Name: "kk", Addr: Address{ Region: "89328", Street: "iuiods", No: "iods", }, } fmt.Printf("%#v\n", u) fmt.Println(u.User()) //[1]kk:{89328 iuiods iods} fmt.Println(u.Addr.Region) //89328 fmt.Println(u) //[1]kk:{89328 iuiods iods} }
java中的this, 但是在go中一定需要写一个对象
package main import ( "fmt" ) type User struct { id int name string } func (user User) GetId() int { return user.id } func (user *User) SetId(id int) { user.id = id } func (user *User) GetName() string { return user.name } func (user *User) SetName(name string) { user.name = name } type Employee struct { User Salary float64 name string } func (employee Employee) GetName() string { return employee.name } func (employee * Employee) SetName(name string) { employee.name = name } func main() { u := User{ id: 1, name: "张三", } u.SetId(10) fmt.Println(u.id) u.SetName("哈哈") fmt.Println(u.GetName()) //哈哈 e := Employee{ User: User{1, "kk"}, Salary: 1000, name: "xiaoke", } fmt.Println(e.GetName()) //xiaoke fmt.Println(e.User.GetName()) //kk e.SetName(" set userName ") //设置的是user的Name fmt.Println(e.GetName()) // 获取到Employee的Name fmt.Println(e.User.GetName()) // 获取用户名 e.SetName("哈哈") fmt.Println("----------",e.GetName()) // 哈哈 }
方法:
指针接收者
该使用的值接收者还是指针接收者,取决于是否现需要修改原始结构体,若不需要修改则使用值,若需要修改则使用指针,若存在指针接收者,则所有方法的使用指针接收者。
对于 接收者为指针类型的方法 ,需要注意在运行时若接收者为nil用会发生错误 。
若结构体中匿名嵌入带有方法的结构体时,则在外部结构体可以嵌入结构体的方法,并且 在调用时只有嵌入字段会传递给嵌入结构体方法的接收者。
当被嵌入结构体与嵌入结构体具有相同的名称时,则使用对象,方法名调用被嵌入结构体方法,若想要调用嵌入结构体方法,则使用对象嵌入结构体名,方法 。
方法值/方法表达式
方法可以赋值给变量,存储在数组,切片,映射中,可以作为参数传递给函数返回值进行返回 。
方法有两种,一种时使用对象/对象指针调用的方法值,另外一种有类型,类型调用的(方法表达式)
方法值 。
在方法表达式赋值时若方法接收者为值类型,则在赋值时会将值类型拷贝(或调用为指针类型则自动解引用拷贝)
package main import "fmt" type Dog struct { name string } func (dog Dog) Call() { fmt.Printf("%s: 汪汪:", dog.name) } func (dog *Dog) SetName(name string) { dog.name = name } func main() { dog := Dog{"豆豆"} m1 := dog.Call fmt.Printf("%T \n", m1) m1() }
package main import "fmt" type Dog struct { name string } func (dog Dog) Call() { fmt.Printf("%s %#v : 汪汪\n", dog.name,&dog) } func (dog * Dog) CallPoint() { fmt.Printf("%s %#v : 汪汪\n", dog.name,&dog) } func (dog *Dog) SetName(name string) { dog.name = name fmt.Printf("%#v \n",&dog) } func main() { dog := Dog{"豆豆"} m1 := dog.Call fmt.Printf("%T \n", m1) //func() m1() // 豆豆 : 汪汪 dog.SetName("小黑") // m1() //豆豆 : 汪汪 fmt.Println("============================") // 对于值接收者方法 者会拷备一份 pdog := &Dog{"豆豆"} m2 := pdog.Call fmt.Printf("%T \n",m2) //func() m2() //豆豆 : 汪汪 pdog.SetName("小黑") m2() //豆豆 : 汪汪 fmt.Println("============================") // 对于值接收者方法 者会拷备一份 pdog1 := &Dog{"豆豆"} m3 := pdog1.CallPoint fmt.Printf("%T \n",m3) //func() m3() //豆豆 (**main.Dog)(0xc00000e040) : 汪汪 pdog1.SetName("小黑") m3() //小黑 (**main.Dog)(0xc00000e050) : 汪汪 }
结构体排序
package main import ( "fmt" "sort" ) type User struct { ID int Name string } func main() { list := [][2]int{{1, 3}, {5, 9}, {4, 3}, {6, 2}} //使用数组中第二个元素比较大小,元素比较大小进行排序 sort.Slice(list, func(i, j int) bool { return list[i][1] < list[j][1] }) fmt.Println(list) //从小到大开始排序 users := []User{ {ID: 1, Name: "zhangsan"}, {ID: 2, Name: "lisi"}, {ID: 4, Name: "wangwu"}, {ID: 3, Name: "zhaoliu"}, } sort.Slice(users, func(i, j int) bool { return users[i].ID < users[j].ID //从小到大开始排序 }) fmt.Println(users) //[{1 zhangsan} {2 lisi} {3 zhaoliu} {4 wangwu}] }
作业 将用户管理系统改成结构体
package manager import ( "fmt" "sort" "strings" ) type User struct { ID int RealName string } //添加用户 func AddUser(users *[]User) { start: var ( id int name string ) fmt.Println("请输入姓名或退出(q/Q):") fmt.Scan(&name) if name == "q" || name == "Q" { return } if exits(users, name) { fmt.Println(name, " 名字已经存在") goto start } id = GetmaxId(users) user := User{ID: id, RealName: name} *users = append(*users, user) for _, v := range *users { fmt.Printf("%#v \t ", v) } fmt.Println() goto start } func exits(users *[]User, name string) bool { for _, v := range *users { if strings.Contains(v.RealName, name) { return true } } return false } func GetmaxId(users *[]User) int { maxId := 1 for _, v := range *users { if maxId < v.ID { maxId = v.ID } } maxId = maxId + 1 return maxId } //更新用户 func UpdateUser(users *[]User) { fmt.Println("请输入要修改用户姓名:") var inputId string fmt.Scan(&inputId) xx := strings.Split(inputId, "_") fmt.Println(xx) for _, v := range *users { if strings.Contains(v.RealName, xx[0]) { v.RealName = xx[1] break } } } //删除用户 func DeleteUser(users *[]User) { start: fmt.Println("请删除用户姓名:") var inputId string fmt.Scan(&inputId) if inputId == "q" || inputId == "Q" { return } if inputId == "all" { *users = []User{} } else { for k, v := range *users { if strings.Contains(v.RealName, inputId) { *users = append((*users)[:k], (*users)[k+1:]...) break } } } goto start } // func QueryUser(users *[]User) { start: fmt.Println("请输入要查询的用户姓名或退出(q/Q):") var inputId string fmt.Scan(&inputId) if inputId == "q" || inputId == "Q" { return } if inputId == "all" { sort.Slice(*users, func(i, j int) bool { return (*users)[i].RealName > (*users)[j].RealName }) for _, v := range *users { fmt.Printf("%5d | %20s\n", v.ID, v.RealName) } } else { for _, v := range *users { if strings.Contains(v.RealName, inputId) { fmt.Printf("%5d | %20s \n", v.ID, v.RealName) break } } } goto start } package main import ( "fmt" "go_learn/20211111/codes/manager" "os" ) func main() { callbacks := map[string]func(users *[]manager.User){ "1": manager.AddUser, "2": manager.UpdateUser, "3": manager.DeleteUser, "4": manager.QueryUser, } fmt.Println(callbacks) //存储用户信息 users := []manager.User{} fmt.Println("欢迎使用用户管理系统:") //id := 0 for { var op string fmt.Println(`请输入指令: 1.新建用户 2.修改用户 3.删除用户 4.查询用户 q.退出`) fmt.Scan(&op) if "q" == op { os.Exit(500) //直接退出 } callbacks[op](&users) } }
github地址
https://github.com/quyixiao/go_learn.git