Go 结构体学习笔记

Go语言可以通过自定义的方式形成新的类型,结构体就是这些类型中的一种复合类型,结构体是由零个或多个任意类型的值聚合成的实体,每个值都可以称为结构体的成员。

关键词

  • 定义结构体

    • 普通结构体

    • 匿名结构体

      • 提升字段
    • 结构体嵌套

  • 结构体外部访问

  • 结构体比较

  • 结构体和结构体指针

    • 使用

    • 方法调用

    • 作为参数使用

  • make和new

|

定义结构体

普通结构体

//常规结构体定义 ,字段名称+ 类型                                     
type Info struct {
   name string
   id  int
}

匿名结构体

//匿名结构体定义
type Info2 struct {
   id  int
   Info // Info结构体内部的字段又叫提升字段(我觉得叫啥无所谓)
}
//此处允许名称相同,并且数据结构不同的字段。
//访问时遇到名称相同的字段优先访问外层

var info_new = Info2{1,Info{"lisi",3}}
log.Println(info_new.id) // 1
log.Println(info_new.Info.id) // 3
log.Println(info_new.name) // lisi  可作为外层成员直接访问
//如果出现多层匿名嵌套情况,无论哪层的不重复的成员都可以作为最外层访问

//在结构体中属于匿名结构体的字段称为提升字段,因为它们可以被访问,就好像它们属于拥有匿名结构字段的结构一样。

type Info3 struct {
   name3 string
   id3  int
   Info2
}

var info_new = Info3{"王二麻子", 3,Info2{3 , Info{"张三",3}}}
log.Println(info_new. name) // 张三  可作为外层成员直接访问

//强调 :如果出现多层匿名嵌套情况,无论哪层的不重复的成员都可以作为最外层访问 但不建议这么搞,因为你这么写了我肯定看不懂

结构体嵌套

//结构体嵌套

type Info2 struct {
   id  int
   info Info
}
//就是给匿名的结构体加一个变量名称
info_new = Info2{3 , Info{"张三",3}}
var info_new = Info2{
   id:3 , 
   Info:Info{"张三",3},
}

结构体外部访问

//其实外部访问的问题,跟方法一样当你的结构体名称大写开头的时候可以被其他包访问
//当你的成员变量大写开头时可以被外部包访问

type Info struct { //-> y
   Id  int         //-> y
   Name string     //->  y 
   name2 string    //-> no
}

type info2 struct {  //->no
   Id int            //->y
   name string       //->no
}

//Info 应该好理解,那么什么时候使用 info2 的id呢 ?
//我们看一个比较贱的例子

//在包里定义一个返回info2 的方法 
func Create() info2 {
   return info2{12,"张三"}
}
//然后在main函数里

package main

import (
   "golangany/GoStruct"

   "log"
)

func main() {
   log.Println(GoStruct.Create().Id) // 12
}

//备注 但是这里如果是直接打印结构体  
log.Println(GoStruct.Create()) // {12 张三}

结构体比较

//结构体比较
//1\. 比较的前提是结构体的成员都是值类型的 

type Info struct {
   id  int
   name string
}

var a = Info{1,"zhangsan"}
var b = Info{1,"zhangsan"}

log.Println(a==b) //true

//非值类型比较 --------------错误示范

image

当我想尝试另一个骚操作的时候

image

结构体和结构体指针

简单使用

//结构体和结构体指针
//简单使用

type Info struct {
   id  int
   name string
}
var a = Info{12,"张三"}
a.id =13
log.Println(&a ,a)
(&a).id = 15
log.Println(&a ,a)

//当初始化完局部变量的结构体对象,和结构体指针的效果是一致的,都可以改变当前对象的属性

//参数传递 
package main

import "log"

type Info struct {
   id  int
   name string
}

func StructSet( i Info) {
   i.id = 50
}

func StructSet2( i *Info) {
   i.id = 50
}

func main() {
   i := Info{id: 12,name: "张三"}
   StructSet(i)
   log.Println(i) // {12 张三}
   StructSet2(&i)
   log.Println(i) // {50 张三}
}

//所以当传递结构体指针作为变量的时候,是可以修改原结构体对象的值

//结构体方法调用

package main

import "log"

type Info struct {
   id  int
   name string
}

func ( i Info)StructSet() { // == StructSet( i Info)
   i.id = 50
}

func( i *Info) StructSet2() {//== StructSet2( i *Info) 
   i.id = 50
}

func main() {
   i := Info{id: 12,name: "张三"}
   i.StructSet()
   log.Println(i) // {12 张三}
   i.StructSet2() //== (&i).StructSet2() 
   log.Println(i) // {50 张三}
}

//注意这里  在这里是不是用 & 效果是一样的

func create() (*Info){
   i := Info{id: 12,name: "张三"}
   return  &i
}

func main() {
   i2 := create()
   i2.StructSet()
   log.Println(i2)
   i2.StructSet2()
   log.Println(i2)
}

//我们这里使用一个新的方式来调用看看 
//效果其实是一样的 ,那么使用 结构体指针和 传值方式调用的区别是什么呢

//我觉得 
//1\. StructSet2( i *Info)  调用方需要关注传入的是指针,还是结构体本身
//2\. i2.StructSet()   这种方式传值时,由方法来控制我使用的是指针还是结构体副本,调用方不感知
//3\. 个人觉得 如果你的方法中只有读取操作尽量使用 不带指针的函数写法,避免误操作导致修改数组,增加代码安全性

make和new

  • make和new都是golang用来分配内存的內建函数,且在堆上分配内存,make 即分配内存,也初始化内存。new只是将内存清零,并没有初始化内存。

  • make返回的还是引用类型本身;而new返回的是指向类型的指针。

  • make只能用来分配及初始化类型为slice,map,channel的数据;new可以分配任意类型的数据。

没想到吧我先看下var

//开始之前先说下 var 关键字吧

package main

import (
   "fmt"
   "log"
   "unsafe"
)

type Info struct {
   id  int
   name string
}

func main() {
   var a_int int
   fmt.Printf("a_int的数据类型是%T,a的字节大小是%d 开始地址 %p \n",a_int,unsafe.Sizeof(a_int),&a_int)
   var b_int []int
   fmt.Printf("b_int的数据类型是%T,a的字节大小是%d 开始地址 %p \n",b_int,unsafe.Sizeof(b_int) ,&b_int)
   b_int = append(b_int, 1,2,3,4,5)
   fmt.Printf("b_int的数据类型是%T,a的字节大小是%d 开始地址 %p \n",b_int,unsafe.Sizeof(b_int),&b_int)
   log.Println(b_int)
   var c_int [4]int
   fmt.Printf("c_int的数据类型是%T,a的字节大小是%d 开始地址 %p  \n",c_int,unsafe.Sizeof(c_int),&c_int)
   var d_int map[string]int
   fmt.Printf("d_int的数据类型是%T,a的字节大小是%d 开始地址 %p  \n",d_int,unsafe.Sizeof(d_int),&d_int)
   var e_int Info
   fmt.Printf("e_int的数据类型是%T,a的字节大小是%d 开始地址 %p  \n",e_int,unsafe.Sizeof(e_int),&e_int)
}

//a_int的数据类型是int,a的字节大小是8 开始地址 0xc00001e0a8 
//b_int的数据类型是[]int,a的字节大小是24 开始地址 0xc00000c030 
//b_int的数据类型是[]int,a的字节大小是24 开始地址 0xc00000c030 
//2022/03/05 16:26:30 [1 2 3 4 5]
//c_int的数据类型是[4]int,a的字节大小是32 开始地址 0xc0000160c0  
//d_int的数据类型是map[string]int,a的字节大小是8 开始地址 0xc00000e030  
//e_int的数据类型是main.Info,a的字节大小是24 开始地址 0xc00000c078  

首先确定一个事情就是,var 声明变量后并给其分配了内存空间,无论最后你有没有赋值,当然我觉得这块跟make还是new没关系哈哈哈

Make和new

差异1 make用于内建类型(map、slice 和channel)的内存分配

差异2 返回数据还是返回指针

差异3 make可以给定长度并且赋初始值


package main

import "log"

func main() {
    //make用于内建类型(map、slice 和channel)的内存分配
    //本质来讲,导致这三个类型有所不同的原因是指向数据结构的引用在使用前必须被初始化。例如,一个slice,是一个包含指向数据(内部array)的指针、长度和容量的三项描述符;
    //不知道是不是说,这三种数据结构本质是个结构体,使用的前提是必须要将里面主要的值进行初始化,也就是说可能在内部实现的时候  new(channl) 然后给它赋值了
    a := make(map[int]int)
    log.Println(a) //2022/03/05 16:39:05 map[]
    c := make([]int ,4)
    log.Println(c) // [0 0 0 0] 可赋值 0 "" 以及 nil
    b := new(map[int]int)
    log.Println(b) //2022/03/05 16:39:05 &map[]
}
//可以看出 new返回了数据指针 ,而make返回了数据

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 228,333评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,491评论 3 416
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 176,263评论 0 374
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,946评论 1 309
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,708评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,186评论 1 324
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,255评论 3 441
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,409评论 0 288
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,939评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,774评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,976评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,518评论 5 359
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,209评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,641评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,872评论 1 286
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,650评论 3 391
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,958评论 2 373

推荐阅读更多精彩内容