• GO语言结构体


    什么是结构体

    结构体是用户定义的类型,表示若干个字段(Field)的集合。

    结构体的声明

    例如声明一个人, 有年龄age, 身高height, 体重weight, 可以将这三个属性组合在一起

    type People struct {
    	age    int
    	weight int
    	height int
    }
    

    上面的结构体People为结构体的名称, 称为命名的结构体, 我们也可以声明匿名结构体:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        emp3 := struct {
            firstName, lastName string
            age, salary         int
        }{
            firstName: "Andreah",
            lastName:  "Nikola",
            age:       31,
            salary:    5000,
        }
    
        fmt.Println("Employee 3", emp3)
    }
    

    上面声明了一个匿名接口体, 并在声明的同时给匿名结构体赋值 

    结构体零值

    当声明的结构体变量并没有被显式地初始化时,该结构体的字段将默认赋为零值。

    结构体指针

    如下, 创建一个结构体指针

    package main
    
    import (
    	"fmt"
    )
    
    type People struct {
    	name                string
    	age, weight, height int
    }
    
    func main() {
    	emp := &People{"andy", 48, 80, 175}
    	fmt.Println("Name:", (*emp).name)
    	fmt.Println("Age:", (*emp).age)
    }
    

    emp是一个结构体指针变量, (*emp).name表示访问结构体emp的那么字段, GO语言允许结构体指针在访问字段时,使用emp.name 这也是GO语言的语法糖

    匿名字段

    GO语言允许结构体内有匿名字段,如

    type Person struct {  
        string
        int
    }
    

    匿名字段的名称默认为它的类型, 比如上面Person结构体, 它有两个匿名字段, 但GO会默认这些字段名为他们的类型, 所以Person实际上有两个名为string和int的字段, 不过由于这个原因, 结构体内不能存在相同类型的匿名字段, 否则会报错

    结构体作为函数参数

    结构体作为函数参数有值参数和指针参数区别, 指针参数只可以接收结构体指针,同样值参数只能接收结构体值变量, 例如:

    package main
    
    import (
    	"fmt"
    )
    
    type person struct {
    	age  int
    	name string
    }
    
    func print(r person) {
    	fmt.Printf("name: %s, age : %d
    ", r.name, r.age)
    }
    
    func main() {
    	r := person{
    		name: "andy",
    		age:  18,
    	}
    	print(r)
    	p := &r
    	/*
    	   ccannot use p (type *person) as type person in argument to print
    	*/
    	print(p)
    }
    

    此代码编译会抛出错误:ccannot use p (type *person) as type person in argument to print

    结构体作为方法的接收器

    结构体作为方法的接收器, 分为指针接收器和值接收器, 两者可以混用, 这得益于GO语言的语法糖, 例如:

    package main
    
    import (
    	"fmt"
    )
    type person struct {
    	age  int
    	name string
    }
    func (p person) print() {
    	fmt.Printf("name: %s, age : %d
    ", p.name, p.age)
    }
    func (p *person) printName() {
    	fmt.Printf("name: %s
    ", p.name)
    }
    func main() {
    	r := person{
    		name: "andy",
    		age:  18,
    	}
    
    	r.print()
    	r.printName()
    	p := &r
    	p.print()
    	p.printName()
    }
    //程序输出
    name: andy, age : 18
    name: andy
    name: andy, age : 18
    name: andy  

    为了方便,GO语言把r.printName()解释为(&r).printName(), 把p.print()解释为(*p).print()

    结构体实现接口

    结构体实现接口, 分为指针接受者和值接受者, 使用值接受者声明的方法, 既可以用值来调用,也能用指针调用, 但是使用指针接受者声明的方法, 只能用指针调用
    值接受者声明的方法不会影响接受者(因为是值传递), 所以GO语言在这里加了语法糖(默认将指针变量解释为普通值变量,因为反正不会影响接受者的值), 但是使用指针接受者声明的方法, 是会影响接受者的, 所以必须抛出错误, 以免用户在不知道的情况下,改变了接受者的值, 示例代码如下:

    package main
    
    import "fmt"
    
    type Print interface {
    	Print()
    }
    type Person struct {
    	name string
    	age  int
    }
    
    func (p Person) Print() { // 使用值接受者实现
    	fmt.Printf("%s is %d years old
    ", p.name, p.age)
    }
    
    type Address struct {
    	state   string
    	country string
    }
    
    func (a *Address) Print() { // 使用指针接受者实现
    	fmt.Printf("State %s Country %s", a.state, a.country)
    }
    
    func main() {
    	var d1 Print
    	p1 := Person{"Sam", 25}
    	d1 = p1
    	d1.Print()
    	p2 := Person{"James", 32}
    	d1 = &p2
    	d1.Print()
    
    	var d2 Print
    	a := Address{"Washington", "USA"}
    
    	/* 如果下面一行取消注释会导致编译错误:
    	   cannot use a (type Address) as type Print in assignment:
    	Address does not implement Print (Print method has pointer receiver)
    	*/
    	d2 = a
    
    	//d2 = &a // 这是合法的
    	// 因为在第 22 行,Address 类型的指针实现了 Describer 接口
    	d2.Print()
    
    }

    上面将d2 = a 注释调, 将d2 = &a打开即可正常运行

  • 相关阅读:
    (转)简单自定义控件
    (转)简单自定义控件2
    (转)select 1 from ... sql语句中的1代表什么意思? .
    (转)server.urlencode有什么用?怎么用?
    (转)精通 JS正则表达式
    input属性 disabled与readonly的区别
    Hibernate映射关系之_多对多
    Hibernate关联映射之_一对一
    Hibernate常用方法之_删除
    Hibernate常用方法之_修改
  • 原文地址:https://www.cnblogs.com/y-yxh/p/12837826.html
Copyright © 2020-2023  润新知