最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于golang?struct?中的?slice?無法原子賦值的問題

 更新時(shí)間:2024年01月20日 09:13:17   作者:ahfuzhang  
這篇文章主要介紹了為什么?golang?struct?中的?slice?無法原子賦值的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

golang struct 中的 slice 無法原子賦值

有這樣一個(gè)結(jié)構(gòu)體:

type MySt struct{
    Field []byte
}

我在數(shù)組排序中想要交換值:

func Swap(arr []MySt, i,j int){
    arr[i], arr[j] = arr[j], arr[i]
}

我猜測,就算其成員 Field 是引用類型,但是引用的指針也會(huì)交換,應(yīng)該是沒問題的。
實(shí)際測試這里復(fù)制錯(cuò)誤了。

于是我換個(gè)寫法:

func Swap(arr []MySt, i,j int){
    arr[i].Field, arr[j].Field = arr[j].Field, arr[i].Field
}

上面的代碼仍然是不行。
猜測是編譯期產(chǎn)生的代碼不是類似 memcpy() 這種,而是逐個(gè)成員去交換,交換到指針這里時(shí),無法做到原子的交換,從而出了問題。

改成下面的方法,終于對(duì)了:

func Swap(arr []MySt, i,j int){
    arr[i].Field, arr[j].Field = swapSlice(arr[j].Field, arr[i].Field)
}
func swapSlice(a, b []byte) ([]byte, []byte) {
	return b, a
}

仍然無法理解我為社么錯(cuò)了,求指教。

golang struct注意事項(xiàng)

 struct注意事項(xiàng):

1.字段聲明語法同變量,示例: 字段名  字段類型

2.字段的類型可以為:基本類型、數(shù)組或引用類型

3.在創(chuàng)建一個(gè)結(jié)構(gòu)體變量后,如果沒有給字段賦值,都對(duì)應(yīng)一個(gè)零值(默認(rèn)值),布爾類型是false,數(shù)值是0,字符串是""。                                                                                                                 

數(shù)組類型的默認(rèn)值和它的元素類型相關(guān),比如score[3]int 則為[0,0,0]                                     

指針,slice,和map的零值都為nil,即還沒有分配空間

type Person struct {
	Name  string
	Age   int
	Score [5]float64
	ptr   *int
	slice []int
	map1  map[string]string
}
func main() {
	var p1 Person
	fmt.Println(p1)
    fmt.Println()
	if p1.ptr == nil {
		fmt.Println("ok1")
	}
	if p1.slice == nil {
		fmt.Println("ok2")
	}
	if p1.map1 == nil {
		fmt.Println("ok3")
	}
	//使用 slice 一定要先make
	p1.slice = make([]int, 10)
	p1.slice[0] = 100
	p1.map1 = make(map[string]string)
	p1.map1["key1"] = "tom"
	fmt.Println(p1)
}

 結(jié)果為:

4.不同結(jié)構(gòu)體變量的字段是獨(dú)立,互不影響,一個(gè)結(jié)構(gòu)體變量字段的改變,不影響另外一個(gè)。因?yàn)榻Y(jié)構(gòu)體是值類型,不是引用類型。

type Monster struct {
	Name string
	Age  int
}
func main() {
	var monster1 Monster
	monster1.Name = "牛博文"
	monster1.Age = 500
	monster2 := monster1
	monster2.Name = "蕪湖"
	fmt.Println("monster1 = ", monster1)
	fmt.Println("monster2 = ", monster2)
}

 結(jié)果:

monster2的改變并沒有影響monster1。但如果想要monster2的改變影響monster1,那么應(yīng)該把monster2變?yōu)橹羔槪?/p>

monster2 := &monster1
	monster2.Name = "蕪湖"
	fmt.Println("monster1 = ", monster1)
	fmt.Println("monster2 = ", *monster2)

 此時(shí)結(jié)果為:

5. 不能這樣寫:*p2.Name  會(huì)報(bào)錯(cuò),因?yàn)?的運(yùn)算符優(yōu)先級(jí)比*高,應(yīng)該:(*p2).Name

6. 結(jié)構(gòu)體中所有字段在內(nèi)存中是連續(xù)的 

r1 := Rect{Point{1, 2}, Point{3, 4}}
	fmt.Println(r1)
	//r1有四個(gè)int,在內(nèi)存中是連續(xù)分布的
	//打印地址
	fmt.Printf("r1.leftUp.x的地址是 %p\n", &r1.leftUp.x)
	fmt.Printf("r1.leftUp.y的地址是 %p\n", &r1.leftUp.y)
	fmt.Printf("r1.righttUp.x的地址是 %p\n", &r1.rightUp.x)
	fmt.Printf("r1.rightUp.y的地址是 %p\n", &r1.rightUp.y)
	fmt.Println()
	//r2有兩個(gè) *Point類型,這兩個(gè)*Point類型的本身地址是連續(xù)的,但是他們指向的地址不一定是連續(xù)的
	r2 := Rect2{&Point{10, 20}, &Point{30, 40}}
	//打印地址
	fmt.Printf("r2.leftUp 本身的地址是%p\n", &r2.leftUp)
	fmt.Printf("r2.rightUp 本身的地址是%p\n", &r2.rightUp)
	fmt.Printf("r2.leftUp 指向的地址是%p\n", r2.leftUp) 
	fmt.Printf("r2.rightUp 指向的地址是%p\n", r2.rightUp)
	fmt.Printf("r2.leftUp.x的地址是 %p\n", &r2.leftUp.x)
	fmt.Printf("r2.leftUp.y的地址是 %p\n", &r2.leftUp.y)
	fmt.Printf("r2.righttUp.x的地址是 %p\n", &r2.rightUp.x)
	fmt.Printf("r2.rightUp.y的地址是 %p\n", &r2.rightUp.y)

7. 結(jié)構(gòu)體是用戶單獨(dú)定義的類型,和其他類型進(jìn)行轉(zhuǎn)換時(shí)需要有完全相同的字段(名字,個(gè)數(shù),類) 

type A struct {
	num int
	str string
}
type B struct {
	num int
	str string
}
func main() {
	var a A
	var b B
	a = A(b)
	fmt.Println(a, b)
}     //輸出結(jié)果為 {0 } {0 }

 8. 結(jié)構(gòu)體進(jìn)行type重新定義(相當(dāng)于取別名), Golang認(rèn)為是新的數(shù)據(jù)類型,但是相互之間可以強(qiáng)轉(zhuǎn)

type Student struct {
	Name string
	Age  int
}
type Stu Student
func main() {
	var stu1 Student
	var stu2 Stu
	// stu2 = stu1    這樣會(huì)報(bào)錯(cuò),因?yàn)間olang認(rèn)為Stu是重新定義的結(jié)構(gòu)體
	stu1 = Student(stu2)
	fmt.Println(stu1, stu2)
}    //輸出結(jié)果為:{ 0} { 0}

9. struct的每個(gè)字段上,可以寫上一個(gè)tag,該tag可以通過反射機(jī)制獲取,常見的使用場景就是序列化和反序列化 

type Monsters struct {
	Name  string `json:"name"`   //`json:"name"`就是struct tag
	Age   int    `json:"age"`
	Skill string `json:"skill"`
}
func main() {
	//1. 創(chuàng)建一個(gè)monster變量
	monster := Monsters{"牛魔王", 500, "芭蕉扇"}
	//2. 將monster變量序列化為 json格式字串
    //  json.Marshal函數(shù)中使用了反射
	jsonMonster, err := json.Marshal(monster)
	if err != nil {
		fmt.Println("json 處理錯(cuò)誤", err)
	}
	//如果age, name, skill首字母是小寫,name返回空序列,所以必須要大寫
	//但如果某些程序員或用戶不習(xí)慣大寫,非要小些,那么可以在struct定義的時(shí)候加上 `json:"name"`
	//注意:式鍵盤左上角的``,不是引號(hào)''
	fmt.Println("jsonMonster", jsonMonster)
	fmt.Println("jsonMonster", string(jsonMonster))
}

 創(chuàng)建struct實(shí)例的四種方式

 方式一:

type Person struct {
	Name string
	Age  int
}
func main() {
	p1 := Person{}
	p1.Name = "tom"
	p1.Age = 18
	fmt.Println(p1)     //{tom 18}
}

 方式二:

p2 := Person{"marry", 18}
	fmt.Println(p2)    //{marry 18}

 方式3:

// var person *person = new (Person)
	var p3 *Person = new(Person)
	//因?yàn)閜3是一個(gè)指針,因此標(biāo)準(zhǔn)的給字段賦值
	(*p3).Name = "smith"
	//(*p3).Name = "smith" 也可以這樣寫 p3.Name = "smith"
	//原因:go的設(shè)計(jì)者為了程序員使用方便,底層會(huì)對(duì)p3.Name = "smith"進(jìn)行處理
	//會(huì)給 p3 加上取值運(yùn)算(*p3).Name = "smith"
	p3.Name = "amy"
	(*p3).Age = 30
	fmt.Println(*p3)   //{amy 30}

方式4:

// var person *Person = &person{}
	var person *Person = &Person{}
	//因?yàn)閜erson是一個(gè)指針,因此標(biāo)準(zhǔn)的訪問字段的方法
	//(*person).Name = "scott"
	//go的設(shè)計(jì)者為了程序員使用方便,也可以person.Name = "scott"
	//原因和上面一樣,底層會(huì)對(duì) person.Name = "scott"進(jìn)行處理,會(huì)加上(*person)
	(*person).Name = "scott"
	person.Name = "scott~~"
	(*person).Age = 88
	person.Age = 10
	fmt.Println(*person)

第3種和第4種方式返回的是 結(jié)構(gòu)體指針

結(jié)構(gòu)體指針訪問字段的標(biāo)準(zhǔn)方式應(yīng)該是:(*結(jié)構(gòu)體指針)字段名,比如:(*person).Name = "tom"

但go做了一個(gè)簡化,也支持結(jié)構(gòu)體指針.字段名,比如:preson.Name = "tom "。更符合程序員使用的習(xí)慣,go編譯器底層對(duì)person.Name做了轉(zhuǎn)化(*person).Name

到此這篇關(guān)于為什么 golang struct 中的 slice 無法原子賦值的文章就介紹到這了,更多相關(guān)golang struct  slice 無法原子賦值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文詳解Golang的模塊版本管理與語義版本控制

    一文詳解Golang的模塊版本管理與語義版本控制

    在Golang中,模塊(module)是Go 1.11版本引入的依賴管理系統(tǒng),幫助開發(fā)者管理項(xiàng)目的依賴,在Go模塊推出之前,開發(fā)者通常使用GOPATH和vendor目錄來管理項(xiàng)目的依賴,本文將給大家詳細(xì)介紹Golang的模塊版本管理與語義版本控制,需要的朋友可以參考下
    2023-12-12
  • Golang中反射的常見用法分享

    Golang中反射的常見用法分享

    本篇文章主要為大家詳細(xì)介紹一些Go語言中常見的反射用法,涵蓋了常見的數(shù)據(jù)類型的反射操作。文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-01-01
  • Go語言中空白標(biāo)識(shí)符的具體使用

    Go語言中空白標(biāo)識(shí)符的具體使用

    Go語言的空白標(biāo)識(shí)符作為匿名變量,用于占位和忽略多余值,本文主要介紹了Go語言中空白標(biāo)識(shí)符的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-06-06
  • 深入淺析Go中三個(gè)點(diǎn)(...)用法

    深入淺析Go中三個(gè)點(diǎn)(...)用法

    這篇文章主要介紹了深入淺析Go中三個(gè)點(diǎn)(...)用法,需要的朋友可以參考下
    2021-10-10
  • go基于Gin框架的HTTP接口限速實(shí)踐

    go基于Gin框架的HTTP接口限速實(shí)踐

    HTTP接口在各個(gè)業(yè)務(wù)模塊之間扮演著重要的角色,本文主要介紹了go基于Gin框架的HTTP接口限速實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Go?WaitGroup及Cond底層實(shí)現(xiàn)原理

    Go?WaitGroup及Cond底層實(shí)現(xiàn)原理

    這篇文章主要為大家介紹了Go?WaitGroup及Cond底層實(shí)現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 深入分析Golang Server源碼實(shí)現(xiàn)過程

    深入分析Golang Server源碼實(shí)現(xiàn)過程

    這篇文章深入介紹了Golang Server源碼實(shí)現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • Go語言項(xiàng)目中使用Viper獲取配置信息詳解

    Go語言項(xiàng)目中使用Viper獲取配置信息詳解

    Viper是Go應(yīng)用的完整配置解決方案,它能處理所有類型的配置需求和配置格式,這篇文章主要介紹了Go項(xiàng)目中使用Viper獲取配置信息,需要的可以參考下
    2024-04-04
  • Go語言CSP并發(fā)模型goroutine及channel底層實(shí)現(xiàn)原理

    Go語言CSP并發(fā)模型goroutine及channel底層實(shí)現(xiàn)原理

    這篇文章主要為大家介紹了Go語言CSP并發(fā)模型goroutine?channel底層實(shí)現(xiàn)原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • go項(xiàng)目打包部署的完整步驟

    go項(xiàng)目打包部署的完整步驟

    之前斷斷續(xù)續(xù)的接觸到項(xiàng)目部署,一直沒有詳細(xì)的了解部署,于是最近就好好的專研一下項(xiàng)目的部署,下面這篇文章主要給大家介紹了關(guān)于go項(xiàng)目打包部署的相關(guān)資料,需要的朋友可以參考下
    2022-09-09

最新評(píng)論

贵州省| 阳原县| 美姑县| 永平县| 内乡县| 恭城| 巩义市| 永年县| 北流市| 当雄县| 黄浦区| 确山县| 赤水市| 泾川县| 黔江区| 伽师县| 佛教| 云林县| 临猗县| 习水县| 金门县| 班戈县| 丹阳市| 右玉县| 清徐县| 鄯善县| 贡觉县| 汤原县| 泰安市| 沙河市| 舞钢市| 卢龙县| 昆山市| 南木林县| 隆安县| 田林县| 宜兰县| 新田县| 新沂市| 凤山县| 元氏县|