Go 开发基础入门——3
Go 向函数传递指针参数
-
Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可
package main import "fmt" func main() { /* 定义局部变量 */ var a int = 100 var b int = 200 fmt.Printf("交换前 a 的值 : %d\n", a) fmt.Printf("交换前 b 的值 : %d\n", b) /* 调用函数用于交换值 * &a 指向 a 变量的地址 * &b 指向 b 变量的地址 */ swap(&a, &b) fmt.Printf("交换后 a 的值 : %d\n", a) fmt.Printf("交换后 b 的值 : %d\n", b) } func swap(x *int, y *int) { var temp int temp = *x /* 保存 x 地址的值 */ *x = *y /* 将 y 赋值给 x */ *y = temp /* 将 temp 赋值给 y */ } 输出结果: 交换前 a 的值 : 100 交换前 b 的值 : 200 交换后 a 的值 : 200 交换后 b 的值 : 100
自定义类型Struct
-
Go中的 struct:
可将类型分为命名和未命名两大类。命名类型包括 bool、int、string 等,而 array、slice、map 等和具体元素类型、长度等有关,属于未命名类型。 具有相同声明的未命名类型被视为同一类型。 • 具有相同基类型的指针。 • 具有相同元素类型和长度的 array。 • 具有相同元素类型的 slice。 • 具有相同键值类型的 map。 • 具有相同元素类型和传送方向的 channel。 • 具有相同字段序列 (字段名、类型、标签、顺序) 的匿名 struct。 • 签名相同 (参数和返回值,不包括参数名称) 的 function。 • 方法集相同 ( 方法名、方法签名相同,和次序无关) 的 interface。
-
struct 特点:
1. 用来自定义复杂数据结构 2. struct里面可以包含多个字段(属性) 3. struct类型可以定义方法,注意和函数的区分 4. struct类型是值类型 5. struct类型可以嵌套 6. Go语言没有class类型,只有struct类型 7. 结构体是用户单独定义的类型,不能和其他类型进行强制转换 8. golang中的struct没有构造函数,一般可以使用工厂模式来解决这个问题。 9. 我们可以为struct中的每个字段,写上一个tag。这个tag可以通过反射的机制获取到,最常用的场景就是json序列化和反序列化。
-
可以理解为面向对象编程
struct声明及初始化: 声明: type typeName struct { //... } eg: package main type global struct{} func main() { type local struct{} } 初始化: 方法有几种: package main import ( "fmt" ) type Test struct { int string } var a Test func main() { b := new(Test) //同 var b *Test = new(Test) c := Test{1, "c"} d := Test{} e := &Test{} f := &Test{2, "f"} //同 var d *Test = &Test{2, "f"} fmt.Println(a, b, c, d, e, f) // 注: a b c d 返回 Test 类型变量;e f 返回 *Test 类型变量;若无初始化值,则默认为零值 } 输出结果: {0 } &{0 } {1 c} {0 } &{0 } &{2 f}
-
初始化值可以分为两种
a. 有序: typeName{value1, value2, ...} 必须一一对应 b. 无序: typeName{field1:value1, field2:value2, ...} 可初始化部分值 栗子: a:有序 type Person struct { name string age int sex int phone int } func main() { person := Person{"lff", 23, 1, 18135479521} fmt.Println(person) } b: 无序 func main() { p2 := Person{age: 23} //无序,指你可以指定给p2赋哪个字段的值 fmt.Println(person) }
-
操作 struct
声明的struct与普通类型一样 访问结构体中的一个变量名, 用 "." 来连接: varName.field 或 (*varName).field 如操作上面 Person 结构体中的 age : p.age = 35 也可以作为函数中的参数,返回值类型
举个栗子: package main import "fmt" //1. 声明一个自定义类型名为 Person 的结构体 type Person struct { name string age int } func main() { //2. 初始化 var p1 Person p2 := Person{} p3 := Person{"James", 23} p4 := Person{age: 23} fmt.Println(p1, p2, p3, p4) p5 := new(Person) p6 := &Person{} p7 := &Person{"James", 23} p8 := &Person{age: 23} fmt.Println(p5, p6, p7, p8) //3. 操作 p1.age = 50 p2.age = 25 if compareAge(p1, p2) { fmt.Println("p1 is older than p2") } else { fmt.Println("p2 is older than p1") } } func compareAge(p1, p2 Person) bool { if p1.age > p2.age { return true } return false } 输出: { 0} { 0} {James 23} { 23} &{ 0} &{ 0} &{James 23} &{ 23} p1 is older than p2
-
匿名字段
匿名字段: 声明一个 struct1 可以包含已经存在的 struct2 或者go语言中内置类型作为内置字段,称为匿名字段,即只写了 typeName,无 varName,但是 typeName 不能重复。 匿名字段与面向对象程序语言中的继承 声明及初始化: package main import ( "fmt" ) type Person struct { name string age int addr string } type Employee struct { Person //匿名字段 salary int int //用内置类型作为匿名字段 addr string //类似于重载 } func main() { em1 := Employee{Person{"rain", 23, "qingyangqu"}, 5000, 100, "gaoxingqu"} fmt.Println(em1) // var em2 Person = em1 // Error: cannot use em1 (type Employee) as type Person in assignment (没有继承, 然也不会有多态) var em2 Person = em1.Person // 同类型拷贝。 fmt.Println(em2) } 输出结果: {{Murphy 23 帝都} 5000 100 北京} {Murphy 23 帝都} 操作 访问方式也是通过 "." 来连接 相同字段采用最外层优先访问,类似于重载 em1.addr 访问的是 Employee 中最外层的 addr em1.Person.addr 访问的是 Employee 中 Person 中的 addr package main import "fmt" type Person struct { name string age int addr string } type Employee struct { Person //匿名字段 salary int int //用内置类型作为匿名字段 addr string //类似于重载 } func main() { /* var em1 Employee = Employee{} em1.Person = Person{"rain", 23, "帝都"} em1.salary = 5000 em1.int = 100 //使用时注意其意义,此处无 em1.addr = "北京" */ //em1 := Employee{Person{"rain", 23, "帝都"}, 5000, 100, "北京"} //初始化方式不一样,但是结果一样 em1 := Employee{Person: Person{"Murphy", 23, "帝都"}, salary: 5000, int: 100, addr: "北京"} fmt.Println(em1) fmt.Println("live addr(em1.addr) = ", em1.addr) fmt.Println("work addr(em1.Person.addr) = ", em1.Person.addr) em1.int = 200 //修改匿名字段的值 } 输出: {{Murphy 23 帝都} 5000 100 北京} live addr(em1.addr) = 北京 work addr(em1.Person.addr) = 帝都 空结构 "节省" 内存, 如用来实现 set 数据结构,或者实现没有 "状态" 只有方法的 "静态类"。 package main func main() { var null struct{} set := make(map[string]struct{}) set["a"] = null } 不能同时嵌入某一类型和其指针类型,因为它们名字相同。 package main type Resource struct { id int } type User struct { *Resource // Resource // Error: duplicate field Resource name string } func main() { u := User{ &Resource{1}, "Administrator", } println(u.id) println(u.Resource.id) } 输出结果: 1 1
弟弟从事java开发,学习go纯属个人爱好,喜欢go的语法和特点,点击这里移步我的个人博客
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: