G

[Golang基础语法] 结构体

RoLingG Golang 2024-03-17

结构体

  1. Go语言中的结构体(struct)相当于JavaclassJavaScriptclass等,也就是所谓的对象。

    方法:也就是在函数的关键字和方法名中间加入一个特殊的接收器类型,接收器可以是结构体也可以不是,接收器是可以内部访问的。

    // 命名结构体
    type Lesson struct {
        name   string //课程名称
        scores int    //课程分数
        time   int    //课程时间
    }
    
    //给课程绑定一个方法
    func (l Lesson) ShowLessonInfo() { //结构体的'方法'    常用
        fmt.Println("name:", l.name)
        fmt.Println("time:", l.time)
    }
    
    func main() {
        //创建结构体时,使用字段名称对每个字段进行初始化
        lesson0 := Lesson{
            name:   "lesson0",
            scores: 1,
            time:   20,
        }
        lesson0.ShowLessonInfo()
        
        lesson1 := Lesson{"lesson1", 2, 30}
        lesson1.ShowLessonInfo()
    }
    //这下就可能会有疑惑:为什么有了函数又要有方法这种东西?
    //因为Go语言中因为相同名字的方法可以定义在不同的类型上,而相同名字的函数式不被允许的。
    /*
        例如func (author Author) PrintfInfo(){...} 
        与 
        func (lesson Lesson) PrintfInfo(){...}
        这两个同名函数是不冲突的,因为属于不同方法
    */
  2. 组合:例如有一些课程,它们同属于一个班级。那么这些课程就会有这个班级的一些属性。(在其他的语言里这个叫继承,但因为Go语言没有类的概念,所以就不是这个叫法,本质上也有一定的区别)

    另外:组合也不止能组合一个,可以是多组合,例如猫是动物,也是好朋友,这下猫就可以组合这两个结构体。

    // 命名结构体
    type Lesson struct {
        Class         //Lesson组合了Class,其实说是继承也对
        name   string //课程名称
        scores int    //课程分数
        time   int    //课程时间
    }
    
    type Class struct {
        name string //班级名称
    }
    
    func (l Lesson) classInfo() {
        fmt.Printf("班级:%s 名字:%s\n", l.Class.name, l.name)
    }
    
    func main() {
        class0 := Class{"计算机一班"}
        lesson0 := Lesson{
            Class:  class0,
            name:   "高数",
            scores: 1,
            time:   20,
        }
        lesson0.classInfo()
    }
  3. 结构体指针:和常见的变量指针差不多,例如我要修改课程的名字,如果不使用指针的话,即便方法里写了修改,输出出来还是没修改的值。(详情请看函数篇里有说明为什么,与存放在内存的地址有关)

    简短一点就是:指针接收器能改变值,而值接收器不能改变。(和c++的函数指针、引用几乎差不多一个意思,与封装性有关)

    // 命名结构体
    type Lesson struct {
        Class         //Lesson组合了Class
        name   string //课程名称
        scores int    //课程分数
        time   int    //课程时间
    }
    
    type Class struct {
        name string //班级名称
    }
    
    func (l Lesson) classInfo() {
        fmt.Printf("班级:%s 名字:%s\n", l.Class.name, l.name)
    }
    
    func (l *Lesson) setName(name string) {    //(l lesson)不行,得用指针才能实现修改
        l.name = name
    }
    
    func main() {
        class0 := Class{"计算机一班"}
        lesson0 := Lesson{
            Class:  class0,
            name:   "高数",
            scores: 1,
            time:   20,
        }
        lesson0.classInfo()
        lesson0.setName("线性代数")
        lesson0.classInfo()
    }
    
    //输出:班级:计算机一班 名字:高数
    //       班级:计算机一班 名字:线性代数
  4. 另外有指针方法又有常规方法会出现警告,如果想要消除警告,给全部的方法加上指针变为指针方法就行了,但也相对的会作用于原有的对象。
  5. tag:例如在和Json一起使用里面,tag就会很常见到。

    type Lesson struct {
        Class         //Lesson组合了Class
        Name   string `json:"name"` //课程名称
        Scores int    `json:"scores"` //课程分数
        Time   int    `json:"time"` //课程时间
    }
    
    //但是如果我觉得结构体里面有敏感属性,不想让json转译出来,那么可以像下面这样做
    type Lesson0 struct {
        Class       
        Name   string `json:"name"`
        Scores int    `json:"-"` //这样用-去表示,就不会被json转译出来了。
        Time   int    `json:"time"`
    }
    
    //还有例如我没有定义Lesson里面的Score,但它被用时会默认给对应的零值,如果有需求不想让它变零值,可以像下面这样做。
    type Lesson1 struct {
        Class       
        Name   string `json:"name,omitempty"`    //这样就会忽略Name的零值直接变为空。
        Scores int    `json:"-"` //这样用-去表示,就不会被json转译出来了,这个相当于忽略字段。
        Time   int    `json:"time"`
    }
    
    func main() {
        class0 := Class{"计算机一班"}
        lesson0 := Lesson{
            Class:  class0,
            Name:   "高数",
            Scores: 1,
            Time:   20,
        }
        byteData, _ := json.Marshal(lesson0)
        fmt.Println(string(byteData))
        //输出:{"name":"高数","scores":1,"time":20}
        //输出的是一个非常标准的json,但是你会发现,这段json里面的key都是tag所表示的名字。这就是tag的用法。
    }
    //这里面的``内的内容就是tag
  6. 另外,并不是只有在结构体上才可以调用方法,在非结构体上也可以调用方法。
PREV
[Golang基础语法] Switch语句
NEXT
[Golang基础语法] 自定义数据类型与类型别名

评论(0)

发布评论