Heim  >  Artikel  >  Backend-Entwicklung  >  Konvertierung des Slice-Typs in Go

Konvertierung des Slice-Typs in Go

WBOY
WBOYnach vorne
2024-02-10 15:00:20580Durchsuche

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])
}

Dieser Code schlägt fehl mit:

runtime error: growslice: len out of range

Zum Beispiel, wenn ich die Besetzung ändere in:

addptr := (*[0]string)(unsafe.pointer(*(*uintptr)(address)))

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])
}

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

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

Keine unsicheren Streiche erforderlich. Vereinfacht zu:

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

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

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

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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen