zoukankan      html  css  js  c++  java
  • Go语言学习笔记(十三)之结构体struct

    19.面对对象1之struct结构体

    Go中面向对象是通过struct来实现,struct是用户自定义的类型,首先需要定义struct

      1: type User struct {
    
      2: 	Username string
    
      3: 	Sex string
    
      4: 	Age int
    
      5: 	AvatarUrl string
    
      6: }

    初始化方法1

      1: var user User
    
      2: user.Age = 18
    
      3: user.Username = "user01"
    
      4: user.Sex = ""
    
      5: user.AvatarUrl = "http://my.com/xxx.jpg"

    初始化方法2
    //也可以部分初始化,这样没有初始化的部分具体值就是对应数据的默认值

      1: var user User = User {
    
      2: 	"Username" : "user01",
    
      3: 	// "Age" : 18,
    
      4: 	"Sex" : "",
    
      5: 	"AvatarUrl" : "http://my.com/xxx.jpg",
    
      6: }

    更简单的写法

      1: user := User {
    
      2: 	"Username": "user01",
    
      3: 	"Age": 18,
    
      4: 	"Sex":"",
    
      5: 	"AvatarUrl":"http://my.com/xxx.jpg",
    
      6: }

    结构体类型的指针

    // &User{}和new(User)本质上是一样的,都是返回一个结构体的地址

      1: var user01 *User = &User {}
    
      2: fmt.Pringln(user01)
      1: >>> &{  0 }

    // 序列化的时候传入指针类型,节省内存,如果不传,就是复制了一个新的User。

      1: var user01 *User = &User {
    
      2: 	user01.Age = 18
    
      3: 	//等同于(*user01).Age = 18
    
      4: 	user01.Username = "user01"
    
      5: 	fmt.Printf("user01:%#v
    ", user01)
    
      6: }
      1: >>> user01:&main.User{Username:"user01", Sex:"", Age:18, AvatarUrl:""}

    struct内存布局

    结构体的内存布局:占用一段连续的内存空间,每一块内存指向数据对应的地址

      1: type Test struct {
    
      2: 	A int32
    
      3: 	B int32
    
      4: 	C int32
    
      5: 	D int32
    
      6: }
    
      7: func main() {
    
      8: 	var t Test
    
      9: 	fmt.Printf("a addr:%p
    ", &t.A)
    
     10: 	fmt.Printf("a addr:%p
    ", &t.B)
    
     11: 	fmt.Printf("a addr:%p
    ", &t.C)
    
     12: 	fmt.Printf("a addr:%p
    ", &t.D)
    
     13: }
    
     14: >>> a addr:0xc00000c0b0
    
     15: a addr:0xc00000c0b4
    
     16: a addr:0xc00000c0b8
    
     17: a addr:0xc00000c0bc

    结构体没有专门的构造函数,必要的话要自己写

      1: type User struct {
    
      2: 	Username string
    
      3: 	Sex string
    
      4: 	Age string
    
      5: 	AvatarUrl string
    
      6: }
    
      7: 
    
      8: func NewUser(username string,sex string,age int, avatar string) *User {
    
      9: 	// 第一种写法
    
     10: 	//user := &User {
    
     11: 		//Username : username,
    
     12: 		//Sex : sex,
    
     13: 		//Age : age,
    
     14: 		//AvatarUrl : avatar,
    
     15: 	//}
    
     16: 	//第二种写法
    
     17: 	user := new(User)
    
     18: 	user.Username = username
    
     19: 	user.Sex = sex
    
     20: 	user.Age = age
    
     21: 	user.AvatarUrl = avatar
    
     22: 	return user
    
     23: }
    
     24: 
    
     25: func main() {
    
     26: 	u := NewUser("user01", "", 18, "xxx.jpg")
    
     27: 	fmt.Printf("user=%#v
    ", u)
    
     28: }
      1: >>> user=&main.User{Username:"user01", Sex:"", Age:18, AvatarUrl:"xxx.jpg"}

    匿名字段

    没有名字的字段

      1: type User struct {
    
      2: 	Username string
    
      3: 	Sex string
    
      4: 	int 
    
      5: 	string
    
      6: }
    
      7: 
    
      8: func main() {
    
      9: 	var user User
    
     10: 	user.Username = "user01"
    
     11: 	user.Sex = "man"
    
     12: 	user.int = 100
    
     13: 	user.string = "hello"
    
     14: 	fmt.Println(user)
    
     15: }
      1: >>> user=&main.User{Username:"user01", Sex:"", Age:18, AvatarUrl:"xxx.jpg"}
    
      2: 

    结构体的嵌套

      1: type Address struct {
    
      2: 	Province string
    
      3: 	City string
    
      4: }
    
      5: 
    
      6: type User struct {
    
      7: 	Username string
    
      8: 	Sex string
    
      9: 	address Adress
    
     10: }
    
     11: 
    
     12: func main() {
    
     13: 	user := &User{
    
     14: 		Username:"user01",
    
     15: 		Sex:"man",
    
     16: 		address: Address{
    
     17: 			Province:"beijing",
    
     18: 			City:"beijing",
    
     19: 		},
    
     20: 	}
    
     21: 	fmt.Println(user)
    
     22: 	fmt.Printf("user%#v", user)
    
     23: }
      1: >>> &{user01 man {beijing beijing}}
    
      2: user&main.User{Username:"user01", Sex:"man", address:main.Address{Province:"beijing", City:"beijing"}}

    // 格式化输出时加上#会让输出按照近似go语言的数据结构来。

    字段冲突的问题
    优先使用主结构体里->没有就去嵌套结构体里面找
    字段可见性,大写表示公开访问,小写表示私有,不能跨包访问

    tag是结构体的元信息

    运行时可以通过反射的机制读出来

      1: type User struct {
    
      2: 	Usename string `json:"username", db:"user_name"`
    
      3: 	Sex string `json:"sex"`
    
      4: 	Age int `json:"age"`
    
      5: 	avatarUrl string
    
      6: 	CreateTime string
    
      7: }
      1: package main
    
      2: import (
    
      3: 	"encoding/json"
    
      4: 	"fmt"
    
      5: )
    
      6: type User struct {
    
      7: 	Username string `json:"username"`
    
      8: 	Sex string `json:"sex"`
    
      9: 	Score float32
    
     10: }
    
     11: func main()  {
    
     12: 	user := &User{
    
     13: 		Username:"user01",
    
     14: 		Sex:"",
    
     15: 		Score:99.2,
    
     16: 	}
    
     17: 	data, _ := json.Marshal(user)
    
     18: 	fmt.Printf("json str:%s
    ", string(data))
    
     19: }
      1: >>> json str:{"username":"user01","sex":"","Score":99.2}

    20.面对对象2

    方法的定义:和其他的语言不一样,go语言中不是使用class这个关键词,而且也没有class这个关键词

      1: package main
    
      2: import "fmt"
    
      3: type People struct {
    
      4: 	Name string
    
      5: 	Country string
    
      6: }
    
      7: func (p People) Print() {
    
      8: 	fmt.Printf("name=%s country=%s
    ", p.Name, p.Country)
    
      9: }
    
     10: func (p People) Set(name string, country string)  {
    
     11: 	p.Name = name
    
     12: 	p.Country = country
    
     13: }
    
     14: func main() {
    
     15: 	var p1 People = People {
    
     16: 		Name : "people01",
    
     17: 		Country: "china",
    
     18: 	}
    
     19: 	p1.Print()
    
     20: 	p1.Set("people2", "USA")
    
     21: 	p1.Print()
    
     22: }

    //注意结果是不变的
    //函数不属于任何类型,方法属于特定的类型。

      1: >>> name=people01 country=china
    
      2: name=people01 country=china

    指针类型作为接受者

      1: package main
    
      2: import "fmt"
    
      3: type People struct {
    
      4: 	Name string
    
      5: 	Country string
    
      6: }
    
      7: func (p *People) Print() {
    
      8: 	fmt.Printf("name=%s country=%s
    ", p.Name, p.Country)
    
      9: }
    
     10: func (p *People) Set(name string, country string)  {
    
     11: 	p.Name = name
    
     12: 	p.Country = country
    
     13: }
    
     14: func main() {
    
     15: 	var p1 People = People {
    
     16: 		Name : "people01",
    
     17: 		Country: "china",
    
     18: 	}
    
     19: 	p1.Print()
    
     20: 	p1.Set("people02", "USA")
    
     21: 	// 语法糖(&p1).Set("people02", "USA")
    
     22: 	p1.Print() 
    
     23: }
    
     24: >>> name=people01 country=china
    
     25: name=people2 country=USA

    //注意结果已经改变了

      1: >>> name=people01 country=china
    
      2: name=people2 country=USA

    匿名字段与继承

      1: type Animal struct {
    
      2: 	Name string
    
      3: 	Sex string
    
      4: }
    
      5: 
    
      6: func (a *Animal) Talk() {
    
      7: 	fmt.Printf("i'm talking, i m %s
    ", a.Name)
    
      8: }
    
      9: 
    
     10: type Dog struct {
    
     11: 	Feet string
    
     12: 	*Animal
    
     13: }
    
     14: 
    
     15: func (d *Dog) Eat() {
    
     16: 	fmt.Println("dog is eatting")
    
     17: }
    
     18: 
    
     19: func main() {
    
     20: 	var d *Dog = &Dog {
    
     21: 		Feet:"four feets",
    
     22: 		Animal: &Animal {
    
     23: 			Name:"dog",
    
     24: 			Sex:"",
    
     25: 		},
    
     26: 	}
    
     27: 	d.Name = "dog01"
    
     28: 	d.Sex = ""
    
     29: 	d.Eat()
    
     30: 	d.Talk()
    
     31: }
      1: >>> dog is eating
    
      2: i'm talking, i m dog01

    关于多重继承的冲突,与匿名字段的解决方法一样,通过指定的结构体与.运算符来调用。

    Json序列化与反序列化

    Json序列化

      1: package main
    
      2: 
    
      3: import (
    
      4: 	"encoding/json"
    
      5: 	"fmt"
    
      6: )
    
      7: 
    
      8: type Student struct {
    
      9: 	Id int
    
     10: 	Name string
    
     11: 	Sex string
    
     12: }
    
     13: 
    
     14: type Class struct{
    
     15: 	Name string
    
     16: 	Count int
    
     17: 	Student []*Student
    
     18: }
    
     19: func main() {
    
     20: 	classmate1 := &Class {
    
     21: 		Name :"101",
    
     22: 	}
    
     23: 	count := 0
    
     24: 	for i:=0;i<2;i++ {
    
     25: 		count += 1
    
     26: 		stu := &Student {
    
     27: 			Name:fmt.Sprintf("stu%d", i ),
    
     28: 			Sex : "man",
    
     29: 			Id : i,
    
     30: 		}
    
     31: 		classmate1.Count = count
    
     32: 		classmate1.Student = append(classmate1.Student, stu)
    
     33: 	}
    
     34: 	data, err := json.Marshal(classmate1)
    
     35: 	if err != nil{
    
     36: 		fmt.Println("failed")
    
     37: 		return
    
     38: 	}
    
     39: 	fmt.Printf("json:%s
    ", string(data))
    
     40: }
      1: >>> json:{"Name":"101","Count":2,"Student":[{"Id":0,"Name":"stu0","Sex":"man"},{"Id":1,"Name":"stu1","Sex":"man"}]}

    反序列化

    把代码加到上面的main函数里面

      1: var rawJson = `{"Name":"101","Count":2,"Student":[{"Id":0,"Name":"stu0","Sex":"man"},{"Id":1,"Name":"stu1","Sex":"man"}]}`
    
      2: 
    
      3: var c1 *Class = &Class{}
    
      4: err = json.Unmarshal([]byte(rawJson), c1)
    
      5: if err != nil {
    
      6: 	fmt.Println("failed")
    
      7: }
    
      8: fmt.Printf("c1:%#v
    ", c1)
    
      9: for _, v := range classmate1.Student {
    
     10: 	fmt.Printf("stu:%#v
    ", v)
    
     11: }
      1: >>> c1:&main.Class{Name:"101", Count:2, Student:[]*main.Student{(*main.Student)(0xc00006c570), (*main.Student)(0xc00006c5a0)}}
    
      2: stu:&main.Student{Id:0, Name:"stu0", Sex:"man"}
    
      3: stu:&main.Student{Id:1, Name:"stu1", Sex:"man"}

    小结:Go语言的数据类型分为四种:基础类型,聚合类型,引用类型,和接口类型。
    基础类型:数字,字符串和布尔型
    聚合类型:数组,结构体。聚合类型是通过组合简单类型而得到的。
    引用类型:指针,slice,map,函数,以及channel。引用类型全都指向程序变量或者状态,操作引用数据就会遍及该数据的全部引用。
    接口类型:单独说,略。

    接下来博客上不写任何练习题了。

  • 相关阅读:
    原产地政策,jsonp跨域
    4安德鲁斯.2.2在系统,具有系统权限的应用程序无法读取或写入SD卡
    [学习笔记]批次需求计划系统-简要
    【大话设计模式】——代理模式
    jQuery Mobile发展新闻阅读器,适应iphone和android打电话
    HDN2048(交错复发)
    CodeForces 69D Dot (游戏+记忆)
    Cocos2d-x 3.x plist+png 做动画
    Solr/SolrCloud -error
    Linux fdisk
  • 原文地址:https://www.cnblogs.com/haoqirui/p/10161950.html
Copyright © 2011-2022 走看看