19

struct

 3 years ago
source link: https://studygolang.com/articles/31505
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1、声明

type human struct {
   name string
   age int
   height int
}
var h human
fmt.Printf("%p,%v\n",&h,h)
0xc000004460,{ 0 0}

简化写法

type human struct {
     name string
     age,heignt int
}

使用new

type human struct {
     name string
     age,heignt int
}
h :=new(human)
fmt.Printf("%p,%v\n",h,h)
0xc00005c420,&{ 0 0}

2、实例化

type human struct {
   name string
   age int
   height int
}
var h1 human
h1.name="张三"
h1.age=20
h1.height=180

h2:=human{"李四",21,175}

var h3=human{"王五",20,181}

h4:=human{
    name:"赵六",
    age:22,
    height:175,
}
h5:=human{
    name:"赵六",
    height:175,
}
fmt.Println(h1,h2,h3,h4,h5)
{张三 20 180} {李四 21 175} {王五 20 181} {赵六 22 175} {赵六 0 175}

3、结构体方法

GO的方法是下定义在一个接收者上的一个函数,接收者是某种类型的变量;GO的方法其实就是一个变种的函数

func (接收者) 函数名... 正常的函数结构

值传递

package main

import (
    "fmt"
)
type human struct {
    name string
    age int
    height int
}
func (h human) change(name string){
    h.name=name
        fmt.Println(h)
}
func main() {
    h1:=human{
        name:"张三",
        age:22,
        height:175,
    }
    fmt.Println(h1)
    h1.change("李四")
    fmt.Println(h1)
}
{张三 22 175}
{李四 22 175}
{张三 22 175}

引用传递

package main

import (
    "fmt"
)
type human struct {
    name string
    age int
    height int
}
func (h *human) change(name string){
    h.name=name
    fmt.Println(*h)
}
func main() {
    h1:=human{
        name:"张三",
        age:22,
        height:175,
    }
    fmt.Println(h1)
    h1.change("李四")
    fmt.Println(h1)
}
{张三 22 175}
{李四 22 175}
{李四 22 175}

4、匿名成员

字段的继承,如下,student可以直接方案human的字段name、age、height

type human struct {
    name string
    age int
    height int
}
type student struct {
    human
    grade string
}
func main() {
    stu1:=student{
        human{"小明",8,140},"三年级",
    }
    fmt.Println(stu1)
        fmt.Println(stu1.name,stu1.age,stu1.height,stu1.grade)
}
{{小明 8 140} 三年级}
小明 8 140 三年级

所有的内置类型和自定义类型都是可以作为匿名字段

type human struct {
    name   string
    age    int
    height int
}
type student struct {
    human
    grade string
    string
}
func main() {
    stu1 := student{
        human{"小明", 8, 140}, "三年级", "中关村一小",
    }
    fmt.Println(stu1)
    fmt.Println(stu1.name, stu1.age, stu1.height, stu1.grade, stu1.string)
}
{{小明 8 140} 三年级 中关村一小}
张三 8 140 三年级 中关村一小

字段重载

type student struct {
    human
    grade string
    string
    name string
}
func main() {
    stu1 := student{
        human{"小明", 8, 140}, "三年级", "中关村一小", "张三",
    }
    fmt.Println(stu1.name,stu1.human.name)
}
张三 小明

匿名字段的方法

type human struct {
    name   string
    age    int
    height int
}
type student struct {
    human
    grade string
    string
    name string
}

func (h *human)change(name string)  {
    h.name=name
    fmt.Println(*h)

}

func main() {
    stu1 := student{
        human{"小明", 8, 140}, "三年级", "中关村一小", "张三",
    }
    stu1.change("大明白")
    fmt.Println(stu1.name,stu1.human.name)
}
{大明白 8 140}
张三 大明白

5、匿名结构体

h1:= struct {
        name string
        age int
        height int
    }{
        name:"张三",
        age:22,
        height:175,
    }
    fmt.Println(h1)
{张三 22 175}

结构体内嵌匿名结构体

type User struct {
    RealName string
    Age      int
    Cart     struct {
        Brand string
        Price float64
    }
}
func main() {
    var u User
    u.Age=19
    u.RealName="小明"
    u.Cart.Brand="奔驰"
    u.Cart.Price=100
    fmt.Println(u)
}
{小明 19 {奔驰 100}}

结构体内嵌匿名结构体数组

数组不是要有数量吗?

type User struct {
    RealName string
    Age      int
    Carts     []struct {
        Brand string
        Price float64
    }
}
func main() {
    var u User
    u.Age=19
    u.RealName="小明"
    u.Carts = []struct {
        Brand string
        Price float64
    }{
        {Brand:"本田",Price:100000.00},
        {Brand:"宝马",Price:300000.00},
    }
    fmt.Println(u)
}
{小明 19 [{本田 100000} {宝马 300000}]}
type User struct {
    RealName string
    Age      int
    Carts     []struct {
        Brand string
        Price float64
    }
}
func main() {
    user := User{}
    user.RealName = "张三"
    user.Age =40
    brands:=[]string{"奔驰","宝马","丰田","大众"}
    for _, cart := range brands {
        item := struct {
            Brand string
            Price float64
        }{Brand:cart,Price:100}
        user.Carts = append(user.Carts, item)
    }
    fmt.Println(user)
}
{张三 40 [{奔驰 100} {宝马 100} {丰田 100} {大众 100}]}

可见性

6、tag

在golang中,命名都是推荐都是用驼峰方式,并且在首字母大小写有特殊的语法含义:包外无法引用。但是由经常需要和其它的系统进行数据交互,例如转成json格式,存储到mongodb啊等等。这个时候如果用属性名来作为键值可能不一定会符合项目要求。

Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来。 Tag在结构体字段的后方定义,由一对反引号包裹起来,具体的格式如下:

key1:"value1" key2:"value2"

下面的例子中Name和Age按照tag中json的格式输出了,Height原样输出。

package main

import (
    "encoding/json"
    "fmt"
)
type human struct {
    Name   string `json:"name"`
    Age    int `json:"age"`
    Height int
}
func main() {
    var user1 human
    user1.Name = "测试名"
    user1.Age=20
    user1.Height = 180
    u,err:=json.Marshal(user1)
    if  err == nil{
        fmt.Printf("value: %s", u)
    }
}
{"name":"测试名","age":20,"Height":180}

获取tag

h:=&human{"测试名",20,180}
rf:=reflect.TypeOf(h)
tag := rf.Elem().Field(0).Tag
fmt.Println(tag)
field0 := rf.Elem().Field(0)
fmt.Println(field0.Tag.Get("json"))
json:"name"
name

7、复制

struct是值类型,默认的复制就是深拷贝

h1:=human{"测试名",20,180}
h2:=h1
fmt.Printf("%p,%v\n",&h1,h1)
fmt.Printf("%p,%v\n",&h2,h2)
0xc000004460,{测试名 20 180}
0xc000004480,{测试名 20 180}

直接赋值指针地址

h1:=human{"测试名",20,180}
    h3:=&h1
    fmt.Printf("%p,%v\n",&h1,h1)
    fmt.Printf("%p,%v\n",h3,*h3)
0xc000004460,{测试名 20 180}
0xc000004460,{测试名 20 180}

8、函数传参

值传递

type human struct {
    Name   string `json:"name"`
    Age    int `json:"age"`
    Height int
}

func change(h human)  {
    h.Name="姓名"
    fmt.Printf("%p,%v\n",&h,h)
}

func main() {
    h1:=human{"测试名",20,180}
    fmt.Printf("%p,%v\n",&h1,h1)
    change(h1)
    fmt.Printf("%p,%v\n",&h1,h1)
}
0xc00005c420,{测试名 20 180}
0xc00005c480,{姓名 20 180}
0xc00005c420,{测试名 20 180}

引用传递

func change(h *human)  {
    h.Name="姓名"
    fmt.Printf("%p,%v\n",h,*h)
}

func main() {
    h1:=human{"测试名",20,180}
    fmt.Printf("%p,%v\n",&h1,h1)
    change(&h1)
    fmt.Printf("%p,%v\n",&h1,h1)
}

有疑问加站长微信联系(非本文作者)

eUjI7rn.png!mobile

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK