• GO开发[五]:结构体struct和方法


    Go结构体struct

    Go语言的结构体(struct)和其他语言的类(class)有同等的地位,但Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性。

    package main
    
    import (
    	"fmt"
    )
    //声明
    type Student struct {
    	Id int
    	Name string
    	age int
    }
    
    func main() {
    	var s Student
    	s.Id =1
    	s.Name ="greg"
    	s.age=20
    	fmt.Println(s)
    	fmt.Printf("Name:%p
    ", &s.Name)
    	fmt.Printf("Id:%p
    ", &s.Id)
    	fmt.Printf("Age: %p
    ", &s.age)
    
    	s1 := Student {
    		Id :2,
    		Name:"gregory",
    		age:20,
    	}
    	fmt.Println(s1)
    	s1=s
    	fmt.Println(s1)
    
    	var s2 *Student = &Student{
    		Id:3,
    		age:  20,
    		Name: "greg",
    	}
    	fmt.Println(s2)
    }
    

    结构体指针

    package main
    
    import "fmt"
    
    //结构体指针
    type Student struct {
       Id int
       Name string
    }
    
    func main(){
       s1 := Student{
          Id :2,
          Name:"greg",
       }
       fmt.Println(s1)
    
       var p *Student
       p = &s1
       p.Id =3
       fmt.Println(s1)
    
       var p1 *int
       p1 = &s1.Id
       *p1 = 4
       fmt.Println(s1)
    }
    

    结构体性质

    结构体是用户单独定义的类型,不能和其他类型进行强制转换

    package main
    
    import "fmt"
    
    type integer int
    
    type Student struct {
       Id int
    }
    
    type Stu Student //alias
    
    func main() {
       var i integer = 1000
       var j int = 100
       //j = i cannot use
       j = int(i)
       fmt.Println(j)
    
       var a Student
       a = Student{30}
       fmt.Println(a)
    
       var b Stu
       //a=b  cannot use
       a = Student(b) //转换
       fmt.Println(a)
    }
    

    我们可以为struct中的每个字段,写上一个tag。这个tag可以通过反射的机制获取到,最常用的场景就是json序列化和反序列化。

    type student struct {
        Id int      “this is Id field”
        Name stirng  “this is name field”
    }
    

    序列化和反序列化

    package main
    
    import (
       "fmt"
       "encoding/json"
       "log"
    )
    
    type Student struct {
       Id int
       Name string
    }
    
    func main(){
       s := Student{
          Id:1,
          Name:"greg",
       }
       fmt.Println(s)
       buf,err := json.Marshal(s)
       if err != nil{
          log.Fatalf("marshal error:%s",err)
       }
       fmt.Println(string(buf))
    
    
       str := `{"Id":2,"Name":"alice"}`
       var s2 Student
       err1 := json.Unmarshal([]byte(str),&s2)
       if err1 != nil {
          log.Fatalf("unmarshal error:%s",err)
       }
       fmt.Println(s2)
    }
    //将Student map的数据写入到文件
    

    结构体中字段可以没有名字,即匿名字段

    访问匿名字段

    package main
    
    import (
       "fmt"
       "time"
    )
    
    type Student struct {
       name string
       age  int
    }
    
    type Class struct {
       Student
       name string
       int
       Start time.Time
       age  int
    }
    
    type School struct {
       Student
       Class
    }
    
    func main() {
       var t Class
       t.Student.name = "stu"
       t.Student.age = 100
    
       t.name="cls"
       t.age=80
       t.int=2000
       fmt.Println(t)
    }
    

    匿名字段冲突处理

    package main
    
    import (
       "fmt"
    )
    
    type Student struct {
       name string
       age  int
    }
    
    type Class struct {
       name string
       age  int
    }
    
    type School struct {
       Student
       Class
    }
    
    func main() {
       var t School
       t.Student.name = "stu"
       t.Class.name = "cls"
       fmt.Println(t)
    }
    

    方法

    Golang中的方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,而不仅仅是struct

    定义:func (recevier type) methodName(参数列表)(返回值列表){}
    

    方法调用

    package main
    
    type Point struct {
    	X, Y float64
    }
    
    func (p *Point) ScaleBy(factor float64) {
    	p.X *= factor
    	p.Y *= factor
    }
    
    func main() {
    	//直接指针
    	p := &Point{1,2}
    	p.ScaleBy(2)
    
    	//声明结构体后再用指针指向
    	p1 := Point{1,2}
    	p2 := &p1
    	p2.ScaleBy(2)
    
    	//使用结构体调用,隐式取地址
    	p3 := Point{1,2}
    	p3.ScaleBy(2) //等价于(&p3).ScaleBy(2)
    }
    

    结构体方法调用:

    package main
    
    import "fmt"
    
    type Student struct {
       Id int
       Name  string
       Age   int
       Score int
    }
    
    func (p *Student) init(name string, age int, score int) {
       p.Name = name
       p.Age = age
       p.Score = score
       fmt.Println(p)
    }
    
    func (p Student) get() Student {
       return p
    }
    
    func main() {
       var stu Student
       (&stu).init("stu", 10, 200)
    
       stu1 := stu.get()
       fmt.Println(stu1)
    }
    

    练习:两点之间的距离

    package main
    
    import (
       "fmt"
       "math"
    )
    
    type Point struct {
       X,Y float64
    }
    
    func (p Point) Distance(q Point) float64 {
       return math.Hypot(q.X-p.X, q.Y-p.Y)
    }
    
    func main() {
       p := Point{1,2}
       q := Point{4,6}
       fmt.Println(p.Distance(q))
    }
    

    方法和函数的区别:

    函数调用: function(variable, 参数列表)
    方法:variable.function(参数列表)
    

    指针receiver和值receiver:本质上和函数的值传递和地址传递是一样的

    方法的访问控制:可见性

    通过首字母大小写来控制可见性
    可见性是package级别的

    继承:

    如果一个struct嵌套了另一个匿名结构体,那么这个结构可以直接访问匿名结构体的方法,从而实现了继承。

    package main
    
    import "fmt"
    
    type Student struct {
       Id int
       name   string
    }
    
    func (p *Student) Run() {
       fmt.Println("greg")
    }
    
    type Class struct {
       Student
       golang string
    }
    
    type School struct {
       gregs Student
    }
    
    func main() {
       var c Class
       c.Id = 100
       c.name = "greg2"
       c.golang = "一班"
    
       fmt.Println(c)
       c.Run()
    
       var sch School
       sch.gregs.Id = 100
       sch.gregs.name = "train"
       fmt.Println(sch)
       sch.gregs.Run()
    }
    

    组合和匿名字段:

    ​ 如果一个struct嵌套了另一个匿名结构体,那么这个结构可以直接访问匿名结构体的方法,从而实现了继承。

    ​ 如果一个struct嵌套了另一个有名结构体,那么这个模式就叫组合。

    多重继承:如果一个struct嵌套了多个匿名结构体,那么这个结构可以直接访问多个匿名结构体的方法,从而实现了多重继承。

  • 相关阅读:
    glog入门demo
    gflag的简单入门demo
    caffe库源码剖析——net层
    排序算法的c++实现——计数排序
    docker的/var/lib/docker目录迁移
    SpringCloud Ribbon 负载均衡 通过服务器名无法连接的神坑一个
    Spring Boot Cache使用与整合
    Navicat Keygen
    Windows / Office
    docker swarm 搭建与服务更新
  • 原文地址:https://www.cnblogs.com/ningxin18/p/8353728.html
Copyright © 2020-2023  润新知