Go語言學習查缺補漏ing Day8
來源:
Go語言學習查缺補漏ing Day8
零、前言
一、為什麼map的value值是不可定址的?解決辦法?
先來看下面這段程式碼:
package main
import "fmt"
type Hello struct {
x, y int
}
var m = map[string]Hello{
"hello": Hello{2, 3},
}
func main() {
m["hello"].x = 4
fmt.Println(m["hello"].x)
}
執行上面這個程式會報錯:
# command-line-arguments
.\demo.go:14:15: cannot assign to struct field m["hello"].x in map
為什麼呢?下面來進行詳細說明:
因為map是無法進行定址的,也就是說可以獲取m["hello"].x的值,但是不能對其值進行修改。
究其原因,因為Go的map是通過雜湊表來實現的,說得更具體一點,就是通過陣列和連結串列組合實現的。
並且Go的map也可以做到動態擴容,當進行擴容之後,map的value那塊空間地址就會產生變化,所以無法對map的value進行定址。
但是注意,map與slice切片的擴容有些不同,map是引用型別,擴容後,value引用地址不會變化,所以map value元素不可定址。而slice擴容後是生成一個新的底層陣列。
有什麼解決辦法呢?
解決辦法一:使用臨時變數
package main
import "fmt"
type Hello struct {
x, y int
}
var m = map[string]Hello{
"hello": Hello{2, 3},
}
func main() {
tmp := m["hello"]
tmp.x = 4
m["hello"] = tmp
fmt.Println(m["hello"].x)
}
解決辦法二:使用指標
package main
import "fmt"
type Hello struct {
x, y int
}
var m = map[string]*Hello{
"hello": &Hello{2, 3},
}
func main() {
m["hello"].x = 4
fmt.Println(m["hello"].x)
}
二、遍歷切片的迴圈次數會不會改變
看下面這段程式碼會不會出現死迴圈:
package main
func main() {
values := []int{1, 2, 3}
for value := range values {
values = append(values, value)
}
}
答案是不會出現死迴圈,程式能夠正常退出。
這是因為迴圈次數在for...range 之前就已經確定了,迴圈之內改變切片的長度,並不會影響迴圈次數。
三、 for...range複用臨時變數
看一看下面這段程式碼,你認為會輸出什麼?
package main
import (
"fmt"
"time"
)
func main() {
var s = [...]int{1, 2, 3}
for index, value := range s {
go func() {
fmt.Println(index, value)
}()
}
time.Sleep(time.Second * 3)
}
哈哈,有的小夥伴會不會很奇怪為什麼是輸出一樣的值?
因為這裡使用:=的形式迭代變數,index和value都會在每次迴圈被重用,並不會進行重新宣告。
所以各個協程都是輸出迴圈結束後的index以及value值,而不是每個協程開始時的index以及value值。
那有什麼解決辦法呢?
解決辦法之一:使用函式引數進行傳遞
package main
import (
"fmt"
"time"
)
func main() {
var s = [...]int{1, 2, 3}
for index, value := range s {
go func(index,value int) {
fmt.Println(index, value)
}(index,value)
}
time.Sleep(time.Second * 3)
}
這樣就能解決了。
解決辦法二:使用臨時變數進行傳遞
package main
import (
"fmt"
"time"
)
func main() {
var s = [...]int{1, 2, 3}
for index, value := range s {
i := index
v := value
go func() {
fmt.Println(i, v)
}()
}
time.Sleep(time.Second * 3)
}
這樣也能解決這個問題。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70001864/viewspace-2847487/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Go語言學習查缺補漏ing Day5Go
- Go語言學習查缺補漏ing Day6Go
- Go語言學習查缺補漏ing Day7Go
- Go語言學習查缺補漏ing Day3Go
- Go語言學習查缺補漏ing Day2Go
- Go語言學習查缺補漏ing Day4Go
- Go語言學習查缺補漏ing Day1Go
- 查漏補缺
- [學習筆記]TypeScript查缺補漏(一):類筆記TypeScript
- HashMap 查漏補缺HashMap
- Typescript 查缺補漏TypeScript
- iOS 查漏補缺 - PerformSelectoriOSperformSelector
- Flutter查漏補缺1Flutter
- JavaScript Promise查缺補漏JavaScriptPromise
- ROS灰灰的日常查漏補缺ROS
- [學習筆記]TypeScript查缺補漏(二):型別與控制流分析筆記TypeScript型別
- SLAM 灰灰restudy及查漏補缺—octomapSLAMREST
- 正規表示式的查漏補缺
- C++灰灰的日常查漏補缺C++
- shell基礎知識查缺補漏
- C# 執行緒查漏補缺C#執行緒
- 前端面試查漏補缺--(十三) 記憶體洩漏前端面試記憶體
- 前端面試查漏補缺--(八) 前端加密前端面試加密
- 前端面試查漏補缺--(十五) Event Loop前端面試OOP
- C# 執行緒同步查漏補缺C#執行緒
- 技術棧查漏補缺——架構師架構
- go語言學習Go
- 前端面試查漏補缺--(十) 前端鑑權前端面試
- 前端面試查漏補缺--(九) HTTP與HTTPS前端面試HTTP
- 【查漏補缺】那些漏掉的面試知識面試
- 前端面試查漏補缺--(四) 前端本地儲存前端面試
- 前端面試查漏補缺--(二) 垃圾回收機制前端面試
- Redis基礎你掌握多少了?來查漏補缺?Redis
- [筆記](更新中)CSP-S 2024 查漏補缺筆記
- go語言學習-介面Go
- go語言學習-goroutineGo
- Go語言學習——mapGo
- [查漏補缺]正規表示式匹配演算法演算法