Konvertierung des Slice-Typs in Go

WBOY
Freigeben: 2024-02-10 15:00:20
nach vorne
578 Leute haben es durchsucht

Go 中的切片类型转换

php-Editor Apple führt Sie in die Slice-Typ-Konvertierung in der Go-Sprache ein. In der Go-Sprache ist ein Slice ein dynamisches Array, das häufig zum Speichern und Betreiben einer Gruppe von Elementen desselben Typs verwendet wird. Unter Slice-Typkonvertierung versteht man die Konvertierung eines Slice-Typs in einen anderen Slice-Typ, was in der tatsächlichen Entwicklung sehr häufig vorkommt. In diesem Artikel werden die Überlegungen und praktischen Anwendungen der Slice-Typ-Konvertierung ausführlich vorgestellt, um den Lesern zu helfen, diese Funktion besser zu verstehen und zu verwenden.

Frageninhalt

Ich bin ganz neu, habe einen C++-Hintergrund und bin auf einige seltsame Probleme gestoßen. Der Code lautet wie folgt:

package main

import (
"fmt"
"unsafe"
)

func main() {
     arr := []string { "one", "two", "three" }
     address := unsafe.pointer(&arr)
     addptr := (*[]string)(unsafe.pointer(*(*uintptr)(address)))
     fmt.println((*addptr)[0])
}
Nach dem Login kopieren

Dieser Code schlägt fehl mit:

runtime error: growslice: len out of range
Nach dem Login kopieren

Zum Beispiel, wenn ich die Besetzung ändere in:

addptr := (*[0]string)(unsafe.pointer(*(*uintptr)(address)))
Nach dem Login kopieren

Der obige Code funktioniert einwandfrei.

Ich weiß, dass dies eine Umwandlung in einen Array-Zeiger ist und das Array eine konstante Größe haben muss. Aber wie konvertiere ich es in einen Zeiger auf ein Slice?

Um die Sache noch verwirrender zu machen, ist es möglich, die Slice-Adresse abzurufen und sie einem Zeiger wie diesem zuzuweisen:

func main() {
     arr := []string { "one", "two", "three" }
     var arrPtr *[]string = &arr
     fmt.Println((*arrPtr)[0])
}
Nach dem Login kopieren

Dieses Mal wird alles gut funktionieren, obwohl der Zeiger vom gleichen Typ ist, auf den ich im ersten Beispiel den unsicheren Zeiger umgewandelt habe. Kann jemand helfen zu verstehen, was genau hier vor sich geht?

Problemumgehung

Einige Hintergrundinformationen: Der Slice-Header enthält Zeiger auf das Hintergrundarray, die Länge und die Kapazität.

Der Code im ersten Teil der Frage wandelt den Slice-Header in einen Zeiger auf den Slice-Header um. go vet Der Befehl warnt, dass der Code in der Frage möglicherweise unsafe.pointer missbraucht.

Behoben durch Entfernen der zusätzlichen Dereferenzierungsoperation, sodass der Code von einem Zeiger auf den Slice-Header in einen Zeiger auf den Slice-Header konvertiert wird.

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[]string)(unsafe.pointer((*uintptr)(address)))
fmt.println((*addptr)[0]) // prints one
Nach dem Login kopieren

Keine Konvertierung in *uintptr erforderlich. Vereinfacht zu:

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[]string)(unsafe.pointer(address))
fmt.println((*addptr)[0]) // prints one
Nach dem Login kopieren

Keine unsicheren Streiche erforderlich. Vereinfacht zu:

arr := []string{"one", "two", "three"}
addptr := &arr
fmt.println((*addptr)[0]) // prints one
Nach dem Login kopieren

Verwenden Sie den folgenden Code, um den Backing-Array-Zeiger des Slice in einen Array-Zeiger umzuwandeln. Der Code ist fragil, da er davon ausgeht, dass das erste Wort des Slice-Headers ein Zeiger auf das Hintergrundarray ist.

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[1]string)(unsafe.pointer(*(*uintptr)(address)))
fmt.println((*addptr)[0]) // prints one
Nach dem Login kopieren

Die uintptr-Konvertierung im vorherigen Code-Snippet ist nicht erforderlich. Vereinfacht zu:

arr := []string{"one", "two", "three"}
address := unsafe.Pointer(&arr)
addPtr := (*[]string)(address)
fmt.Println((*addPtr)[0]) // prints one
Nach dem Login kopieren

Ich hoffe, das hilft.

Das obige ist der detaillierte Inhalt vonKonvertierung des Slice-Typs in Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!