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

解決golang中container/list包中的坑

 更新時間:2021年04月26日 10:13:17   作者:msn217  
這篇文章主要介紹了解決golang中container/list包中的坑,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

golang中l(wèi)ist包用法可以參看這篇文章

但是list包中大部分對于e *Element進(jìn)行操作的元素都可能會導(dǎo)致程序崩潰,其根本原因是e是一個Element類型的指針,當(dāng)然其也可能為nil,但是golang中l(wèi)ist包中函數(shù)沒有對其進(jìn)行是否為nil的檢查,變默認(rèn)其非nil進(jìn)行操作,所以這種情況下,便可能出現(xiàn)程序崩潰。

1.舉個簡單例子

Remove()函數(shù)

package main 
import (
 "container/list"
 "fmt"
)
 
func main() {
 l := list.New()
 l.PushBack(1)
 fmt.Println(l.Front().Value) //1
 value := l.Remove(l.Front())
 fmt.Println(value)            //1
 value1 := l.Remove(l.Front()) //panic: runtime error: invalid memory address or nil pointer dereference
 fmt.Println(value1)
}

從程序中可以直觀的看出程序崩潰,原因是list中只有1個元素,但是要刪除2個元素。但是再進(jìn)一步查看一下原因,便會得出如下結(jié)果。

golang中Front()函數(shù)實現(xiàn)如下

func (l *List) Front() *Element {
    if l.len == 0 {
        return nil
    }
    return l.root.next
}

由此可見,當(dāng)?shù)谝淮蝿h除之后。list的長度變?yōu)?,此時在調(diào)用l.Remove(l.Front()),其中l(wèi).Front()返回的是一個nil。

接下來再看golang中Remove()函數(shù)實現(xiàn),該函數(shù)并沒有判定e是否為nil,變直接默認(rèn)其為非nil,直接對其進(jìn)行e.list或者e.Value取值操作。

當(dāng)e為nil時,這兩個操作都將會造成程序崩潰,這也就是為什么上面程序會崩潰的原因。

func (l *List) Remove(e *Element) interface{} {
 if e.list == l {
  // if e.list == l, l must have been initialized when e was inserted
  // in l or l == nil (e is a zero Element) and l.remove will crash
  l.remove(e)
 }
 return e.Value
}

2.(l *list)PushBackList(other *list)

該函數(shù)用于將other list中元素添加在l list的后面。

基本實現(xiàn)思想是取出other中所有元素,將其順次掛載在l列表中,但是golang中實現(xiàn)有問題

代碼如下

func (l *List) PushBackList(other *List) {
 l.lazyInit()
 for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
  l.insertValue(e.Value, l.root.prev)
 }
}

其具體思想是首先獲取other的長度n,然后循環(huán)n次取出其元素將其插入l中。問題就出現(xiàn)在循環(huán)n次,如果在這個過程中other的元素變化的話,例如其中有些元素被刪除了,這就導(dǎo)致e的指針可能為nil,此時再利用e.Value取值,程序便會崩潰。

如下所示

package main
 
import (
 "container/list"
 "runtime"
)
 
func main() {
 runtime.GOMAXPROCS(8)
 l := list.New()
 ls := list.New()
 for i := 0; i < 10000; i++ {
  ls.PushBack(i)
 }
 go ls.Remove(l.Back())
 l.PushBackList(ls) //invalid memory address or nil pointer dereference
}

如程序中所示,再講ls中元素添加到l過程中,如果ls中元素減少,程序便會崩潰。原因如上面分析。

建議:

在golang中如果對與list的操作只有串行操作,則只需要注意檢查元素指針是否為nil便可避免程序崩潰,如果程序中會并發(fā)處理list中元素,建議對list進(jìn)行加寫鎖(全局鎖),然后再操作。注意,讀寫鎖無法保證并行處理list時程序的安全性。

補(bǔ)充:golang list 鏈表

看代碼吧~

package main 
import (
	"container/list"
	"fmt"
)
 
func main() {
	dataList := list.New()
 
	dataList.PushBack(1)	// 插入末尾
	dataList.PushBack(2)
	dataList.PushFront(3)	 // 插入表頭
	dataList.PushBack(4)
	dataList.PushBack(5)
	m := dataList.PushBack(6)
	m1 := dataList.InsertBefore(7,m)	// 6 之前插入 7
	m2 := dataList.InsertAfter(8,m)	// 6 之后插入 8
 
	// 從鏈表頭開始遍歷
	for e := dataList.Front(); e != nil; e = e.Next() {
		fmt.Println(e.Value) // 打印值
	}
 
	fmt.Println("----------------------------------------")
 
	dataList.Remove(dataList.Front())	// 移除頭部
	dataList.MoveBefore(m2, m)	// 將m2移動m之前
	dataList.MoveAfter(m1, m)
	dataList.Remove(m)	// 移除
 
	//PushBackList	// 插入列表
	//PushFrontList	//
 
	// 從鏈表頭開始遍歷
	for e := dataList.Front(); e != nil; e = e.Next() {
		fmt.Println(e.Value) // 打印值
	}
 
	fmt.Println("----------------------------------------")
 
 
	// 從鏈表尾開始遍歷
	for e := dataList.Back(); e != nil; e = e.Prev() {
		fmt.Println(e.Value, " ")
	}
 
	fmt.Println("----------------------------------------")
	dataList.Init()	// 清空鏈表
	// 從鏈表頭開始遍歷
	for e := dataList.Front(); e != nil; e = e.Next() {
		fmt.Println(e.Value) // 打印值
	}
}

運行結(jié)果:

3
1
2
4
5
7
6
8
----------------------------------------
1
2
4
5
8
7
----------------------------------------
7  
8  
5  
4  
2  
1  
----------------------------------------

Process finished with exit code 0

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • Go語言范圍Range的具體使用

    Go語言范圍Range的具體使用

    range關(guān)鍵字在for循環(huán)中用于遍歷數(shù)組,切片,通道或映射的項目,本文主要介紹了Go語言范圍Range的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • 使用Go語言開發(fā)自動化API測試工具詳解

    使用Go語言開發(fā)自動化API測試工具詳解

    這篇文章主要為大家詳細(xì)介紹了如何使用Go語言開發(fā)自動化API測試工具,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以參考下
    2024-03-03
  • Go中的新增對模糊測試的支持

    Go中的新增對模糊測試的支持

    這篇文章主要為大家介紹了Go中的新增對模糊測試的支持,文中還包含了一些功能實驗性測試分析有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • 詳解Go語言如何解決map并發(fā)安全問題

    詳解Go語言如何解決map并發(fā)安全問題

    常說go語言是一門并發(fā)友好的語言,對于并發(fā)操作總會在編譯期完成安全檢查,所以這篇文章我們就來聊聊go語言是如何解決map這個數(shù)據(jù)結(jié)構(gòu)的線程安全問題吧
    2024-04-04
  • Go語言命令行參數(shù)及cobra使用方法

    Go語言命令行參數(shù)及cobra使用方法

    Cobra是關(guān)于golang的一個命令行解析庫,用它能夠快速創(chuàng)建功能強(qiáng)大的 cli應(yīng)用程序和命令行工具,本文主要介紹了Go語言命令行參數(shù)及cobra使用方法,感興趣的可以了解一下
    2024-01-01
  • 從錯誤中學(xué)習(xí)改正Go語言六個壞習(xí)慣提高編程技巧

    從錯誤中學(xué)習(xí)改正Go語言六個壞習(xí)慣提高編程技巧

    這篇文章主要為大家介紹了從錯誤中學(xué)習(xí)改正Go語言五個壞習(xí)慣提高編程技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • go語言的初始化順序,包,變量,init詳解

    go語言的初始化順序,包,變量,init詳解

    這篇文章主要介紹了go語言的初始化順序,包,變量,init詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang標(biāo)準(zhǔn)庫和外部庫的性能比較

    Golang標(biāo)準(zhǔn)庫和外部庫的性能比較

    這篇文章主要介紹Golang標(biāo)準(zhǔn)庫和外部庫的性能比較,下面文章講圍繞這兩點展開內(nèi)容,感興趣的小伙伴可以參考一下
    2021-10-10
  • 通過源碼分析Golang?cron的實現(xiàn)原理

    通過源碼分析Golang?cron的實現(xiàn)原理

    golang實現(xiàn)定時任務(wù)很簡單,只須要簡單幾步代碼即可以完成,最近在做了幾個定時任務(wù),想研究一下它內(nèi)部是怎么實現(xiàn)的,所以將源碼過了一遍,記錄和分享在此。需要的朋友可以參考以下內(nèi)容,希望對大家有幫助
    2022-10-10
  • Go中各種newreader和newbuffer的使用總結(jié)

    Go中各種newreader和newbuffer的使用總結(jié)

    這篇文章主要為大家詳細(xì)介紹了Go語言中各種newreader和newbuffer的使用的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的參考價值,感興趣的小伙伴可以了解下
    2023-11-11

最新評論

德钦县| 蛟河市| 弋阳县| 富裕县| 陈巴尔虎旗| 资中县| 永丰县| 呼和浩特市| 沈阳市| 湖南省| 门源| 花垣县| 西藏| 新巴尔虎右旗| 山阴县| 通许县| 阳江市| 柯坪县| 承德县| 霍林郭勒市| 台前县| 罗山县| 承德市| 长乐市| 德钦县| 汉中市| 繁峙县| 密云县| 收藏| 石嘴山市| 奇台县| 曲水县| 永州市| 沾化县| 玉山县| 虞城县| 五大连池市| 平南县| 利津县| 汽车| 吉隆县|