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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!