zoukankan      html  css  js  c++  java
  • <12>Golang基础进阶——结构体

    Golang基础进阶——结构体

    结构体(struct)

    定义结构体

    type 类型名 struct {
    	字段1 字段1 类型
    	字段2 字段2 类型
    }
    

    示例:

    func main() {
    	var s1 = Student{1, "zs", 'f', 18, "sh"}
    	fmt.Println(s1)
    
    	var s2 = Student{id: 2, age: 25}
    	fmt.Println(s2)
    
    	var s3 Student
    	s3.id = 3
    	s3.age = 26
    	fmt.Println(s3)
    
    	s4 := &Student{4, "zs", 'f', 18, "sh"}
    	fmt.Println(s4)
    	fmt.Println((*s4).id)
    	fmt.Println(s4.id)
    }
    

    指针类型的结构体

    type Player struct {
    	Name        string
    	HealthPoint int
    	MagicPoint  int
    }
    
    func main (){
    	tank := new(Player)
    	fmt.Println(tank) // &{ 0 0}
    	tank.Name = "Canon"
    	(*tank).HealthPoint = 300
    }
    

    提示: Go 语言中,访问结构体指针的成员交量时可以继 使用 "."。这是因为 Go语言为了方便开发者访问结构体指针的成员变量,使用了语法糖技术,将ins.Name 形式转换为 (*ins).Name

    值和指针作为参数

    type Student struct {
    	id   int
    	name string
    }
    
    func temStudent(tmp Student) {
    	tmp.id = 200
    	fmt.Println(tmp)
    }
    
    func temStudent2(tmp *Student) {
    	tmp.id = 300
    	fmt.Println(tmp)
    }
    func main() {
    	var s = Student{1, "zs"}
    	temStudent(s)
    	fmt.Println(s)
    
    	temStudent2(&s)
    	fmt.Println(s)
    }
    

    结构体内存结构

    一个结构体,会占用一段连续的内存空间

    type Student struct {
    	A int32
    	B int32
    	C int32
    	D int32
    }
    func main(){
    	var s Student
    	fmt.Printf("A addr: %p
    ", &s)
    	fmt.Printf("A addr: %p
    ", &s.A)
    	fmt.Printf("B addr: %p
    ", &s.B)
    	fmt.Printf("C addr: %p
    ", &s.C)
    	fmt.Printf("D addr: %p
    ", &s.D)
    }
    

    构造函数

    type User struct {
    	id   int
    	name string
    	age  int
    }
    
    func NewUser(id int, name string, age int) *User {
    	user := &User{
    		id:   id,
    		name: name,
    		age:  age,
    	}
    	return user
    }
    func main() {
    	user := NewUser(1, "wsl", 18)
    	fmt.Println(user)
    }
    

    匿名字段

     go支持只提供类型而不写字段名的方式,也就是匿名字段,也称为嵌入字段

    type Person struct {
    	name string
    	sex  string
    	age  int
    }
    type Student struct {
    	Person
    	id   int
    	addr string
    }
    
    func main() {
    	s1 := Student{Person{"zs", "fa", 20}, 1, "bj"}
    	fmt.Println(s1)
    
    	s2 := Student{Person: Person{"zs", "fa", 20}}
    	fmt.Println(s2)
    
    	s3 := Student{Person: Person{name: "zs"}}
    	fmt.Println(s3)
    }
    

    同名字段的情况

    type Person struct {
    	name string
    	sex  string
    	age  int
    }
    
    type Student struct {
    	Person
    	id   int
    	addr string
    	name string
    }
    
    func main() {
    	var s Student
    	s.name = "z"
    	fmt.Println(s) // {{  0} 0  z}
    
    	s.Person.name = "ww"
    	fmt.Println(s) // {{ww  0} 0  z}
    }
    

    指针类型匿名字段 

    type Person struct {
    	name string
    	sex  string
    	age  int
    }
    
    type Student struct {
    	*Person
    	id int
    }
    
    func main() {
    	s1 := Student{&Person{"z", "m", 18}, 1}
    	fmt.Println(s1) // {0xc00006a300 1}
    }
    

    内置类型和自定义类型

    type Person struct {
    	name string
    	sex  string
    	age  int
    }
    type mystr string
    type Student struct {
    	Person
    	int
    	mystr
    }
    
    func main() {
    	s1 := Student{Person{"zs", "m", 18}, 1, "bj"}
    	fmt.Println(s1)
    }
    

     方法

     格式:

    func (接收参数名 接收类型) 方法名(参数列表)(返回值)
    

    基础类型作为接收者

    type MyInt int
    
    func Add(a, b MyInt) MyInt {
    	return a + b
    }
    
    func (a MyInt) Add(b MyInt) MyInt {
    	return a + b
    }
    
    func main() {
    	var a MyInt = 1
    	var b MyInt = 2
    
    	fmt.Println(Add(a, b))
    	fmt.Println(a.Add(b))
    }
    

    结构体作为接收者

    type Person struct {
    	name string
    	sex  string
    	age  int
    }
    
    func (p Person) PrintInfo() {
    	fmt.Println(p.name, p.sex, p.age)
    }
    func main() {
    	p := Person{"zs", "m", 18}
    	p.PrintInfo()
    }
    

    值语义和引用语义

    type Person struct {
    	name string
    	sex  string
    	age  int
    }
    
    func (p *Person) SetInfoPointer() {
    	(*p).name = "zs"
    	p.sex = "fe"
    	p.age = 20
    }
    func (p Person) SetInfoValue() {
    	p.name = "ls"
    	p.sex = "m"
    	p.age = 20
    }
    func main() {
    	p1 := Person{"ww", "male", 18}
    	fmt.Println(p1) // {ww male 18}
    	p1.SetInfoPointer()
    	fmt.Println(p1) // {zs fe 20}
    	p1.SetInfoValue()
    	fmt.Println(p1) //{zs fe 20}
    }
    

    方法的继承

    type Person struct {
    	name string
    	sex  string
    	age  int
    }
    
    func (p *Person) PrintInfo(){
    	fmt.Println(p.name,p.sex,p.age)
    }
    type Student struct {
    	Person
    	id int
    	addr string
    }
    func main (){
    	p := Person{"zs","m", 20}
    	p.PrintInfo() // zs m 20
    
    	s := Student{id:2,addr:"bj"}
    	s.PrintInfo() //  0
    }
    

    方法的重写

    type Person struct {
    	name string
    	sex  string
    	age  int
    }
    
    func (p *Person) PrintInfo() {
    	fmt.Println(p.name, p.sex, p.age)
    }
    
    type Student struct {
    	Person
    	id   int
    	addr string
    }
    
    func (s *Student) PrintInfo() {
    	fmt.Println("student:", s.name, s.sex, s.age)
    }
    func main() {
    	p := Person{"zs", "m", 18}
    	p.PrintInfo() // zs m 18
    
    	s := Student{Person{"l", "m", 30}, 2, "b"}
    	s.PrintInfo()
    	// 还能调用父类方法
    	s.Person.PrintInfo()
    }
    

    方法的实际运用

    http包中的类型方法

    func main() {
    	client := &http.Client{}
    
    	// 创建一个http请求
    	req, err := http.NewRequest("POST", "http://www.163.com/", strings.NewReader("key=value"))
    
    	// 发现错误就打印并退出
    	if err != nil {
    		fmt.Println(err)
    		os.Exit(1)
    		return
    	}
    
    	// 为标头添加信息
    	req.Header.Add("User-Agent", "myClient")
    
    	// 开始请求
    	resp, err := client.Do(req)
    
    	// 处理请求的错误
    	if err != nil {
    		fmt.Println(err)
    		os.Exit(1)
    		return
    	}
    
    	data, err := ioutil.ReadAll(resp.Body)
    	fmt.Println(string(data))
    
    	defer resp.Body.Close()
    
    }
    

     在本例子使用的 req.Header 类型为 http.Header 就是典型的自定义类型,并且拥有自己的方法。 http.Header 部分定义如下:

    type Header map[string][]string
    
    func (h Header) Add(key, value string) {
    	textproto.MIMEHeader(h).Add(key, value)
    }
    
    func (h Header) Get(key string) string {
    	return textproto.MIMEHeader(h).Get(key)
    }
    

    Header 实际是一个以字符串为键、字符串切片为值的映射。Add() Header 的方法,map 是一个引用类型,因此即便使用(h Header)的费指针接收器,也可以修改map的值。

    time 包中的类型方法

    func main() {
    	fmt.Println(time.Second.String())
    }
    

     time Second一个常量,下面代码的加粗部分就是 time.Second 定义:

    const (
    	Nanosecond  Duration = 1
    	Microsecond          = 1000 * Nanosecond
    	Millisecond          = 1000 * Microsecond
    	Second               = 1000 * Millisecond
    	Minute               = 60 * Second
    	Hour                 = 60 * Minute
    )
    

    Second 的类型为 Duration ,而 Duration 实际是 int64 的类型,定义如下:

    type Duration int64
    
    // 它拥有一个 String 的方法,部分定义如下:
    
    func (d Duration) String() string {
    
    	... ...
    
    	return string(buf[w:])
    }
    

    Duration.String 可以将 Duration 值转为字符串。

    加油,你们是最棒的!
  • 相关阅读:
    表值函数,标量值函数
    考勤率
    精确小数点
    SQL 返回刚插入的值
    xml读取
    备份表
    case,cast
    DDR基础知识
    NXP官方的I.MX6UL板级Uboot源码适配
    高通msm8909打开debug串口
  • 原文地址:https://www.cnblogs.com/Wshile/p/12801848.html
Copyright © 2011-2022 走看看