亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 golang 中實現通用鏈表,它不允許同一鏈表中的不同類型

在 golang 中實現通用鏈表,它不允許同一鏈表中的不同類型

Go
UYOU 2023-06-01 17:58:28
我想制作一個鏈表,它可以保存任何類型的值,但鏈表必須只保存任何一種類型的值。一般來說,當我使用接口來實現這一點時——任何實現節點接口的類型都可以添加到鏈表中。我為此編寫了一個實現,每當將新鍵添加到鏈表時,都會根據頭部鍵的類型檢查鍵的類型。我想了解這是實現它的正確方法還是有更好的方法。該代碼運行良好 - 但我想了解是否有更好或不同的方法來執行此操作。另外 - 當前使用反射包檢查類型的性能影響是什么。有沒有不同的方法來實現同樣的事情。*main.Student 類型不受支持的類型Unsupported type for the type *main.Student################################################################################Printing the linked list *main.ComplexNode &{9 90}  9 + i90 *main.ComplexNode &{8 80}  8 + i80 *main.ComplexNode &{7 70}  7 + i70 *main.ComplexNode &{6 60}  6 + i60 *main.ComplexNode &{5 50}  5 + i50 *main.ComplexNode &{4 40}  4 + i40 *main.ComplexNode &{3 30}  3 + i30 *main.ComplexNode &{2 20}  2 + i20 *main.ComplexNode &{1 10}  1 + i10################################################################################
查看完整描述

2 回答

?
Helenr

TA貢獻1780條經驗 獲得超4個贊

好消息,從 Go 1.18 開始,Go 現在支持泛型。

按照問題中的示例,這里是一個使用泛型的簡化 LinkedList。您可以在此處的操場上修改它。

package main


import "fmt"


type MyNode[T any] struct {

? ? next? *MyNode[T]

? ? value T

}


type MyLinkedList[T any] struct {

? ? head *MyNode[T]

? ? tail *MyNode[T]

}


func (list *MyLinkedList[T]) Add(t T) *MyLinkedList[T] {

? ? // create node

? ? node := &MyNode[T]{nil, t}

? ? // if first node in list

? ? if list.head == nil {

? ? ? ? list.head = node

? ? ? ? list.tail = node

? ? } else {

? ? ? ? list.tail.next = node

? ? ? ? list.tail = list.tail.next

? ? }


? ? return list

}


func (list *MyLinkedList[T]) AddBeforeHead(t T) *MyLinkedList[T] {

? ? node := &MyNode[T]{nil, t}

? ? if list.head != nil {

? ? ? ? node.next = list.head

? ? ? ? list.head = node

? ? } else {

? ? ? ? // make head

? ? ? ? list.head = node

? ? ? ? list.tail = node

? ? }


? ? return list

}


// display the list

func DisplayList[T any](list *MyLinkedList[T]) string {

? ? var out string = ""

? ? iter := list.head

? ? for iter != nil {

? ? ? ? out += fmt.Sprintf("%v -> ", iter.value)

? ? ? ? iter = iter.next

? ? }

? ? return out

}


func (list *MyLinkedList[T]) Display() string {

? ? return DisplayList(list)

}


// for printing node value

// you could also implement Stringer

// but this is besides the point, you can ignore

func (node *MyNode[T]) String() string {

? ? return fmt.Sprintf("<MyNode: %v>", node.value)

}


// helper func: create list from array

func CreateLinkedList[T any](arr []T) *MyLinkedList[T] {

? ? list := &MyLinkedList[T]{}


? ? for _, v := range arr {

? ? ? ? list.Add(v)

? ? }


? ? return list

}


func main() {

? ? // create a list from array of integers

? ? intArr := []int{10, 20, 30, 40, 50, 60}

? ? list1 := CreateLinkedList(intArr)

? ? // create a list from array of strings

? ? strArr := []string{"foo", "bar", "baz", "faz"}

? ? list2 := CreateLinkedList(strArr)


? ? // test inserting at the beginning

? ? list2.AddBeforeHead("hello")


? ? fmt.Println(list1.Display())

? ? fmt.Println(list2.Display())

}


查看完整回答
反對 回復 2023-06-01
?
長風秋雁

TA貢獻1757條經驗 獲得超7個贊

您可以通過使用接口和運行時檢查(正如您所發現的那樣)或使用代碼生成來做到這一點。這些是您在 Go 中用于泛型編程的當前選項。Go 團隊正在努力為語言添加泛型——這是一項正在進行的工作,每個人都可以自由參與討論。一旦泛型存在,它們將提供您在這里尋求的解決方案。

至于接口與代碼生成,有你提到的性能影響。代碼生成將生成更緊湊的代碼,不需要對大多數操作進行運行時檢查;另一方面,它為項目的構建過程增加了一些復雜性。這些是在運行時解決某些事情與在編譯時預先計算事情的通常權衡。


查看完整回答
反對 回復 2023-06-01
  • 2 回答
  • 0 關注
  • 190 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號