In der Go-Sprache verwenden wir häufig die Typkonvertierung, um Datentypen zu konvertieren. Konvertieren Sie beispielsweise ein Slice vom Typ []Byte in einen String vom Typ String. Normalerweise können wir die Funktion „string()“ verwenden, um eine Typkonvertierung durchzuführen, aber in einigen Sonderfällen kann diese Methode Probleme verursachen. In der Go-Sprache wird die Methode „(string)(unsafe.Pointer(&b))“ als „Magic Pointer“-Methode bezeichnet, die zum Konvertieren eines Slice vom Typ []Byte in einen String vom Typ String verwendet wird. Diese Methode funktioniert jedoch nicht für den Typ bufio.Reader. Warum? Beantworten wir diese Frage.
Ich habe eine Datei. Es hat eine IP
1.1.1.0/24 1.1.2.0/24 2.2.1.0/24 2.2.2.0/24
Ich habe diese Datei zum Slicen gelesen und das []Byte mit *(*string)(unsafe.pointer(&b)) in einen String analysiert, aber es funktioniert nicht
func testinitiprangefromfile(t *testing.t) { filepath := "/tmp/test" file, err := os.open(filepath) if err != nil { t.errorf("failed to open ip range file:%s, err:%s", filepath, err) } reader := bufio.newreader(file) ranges := make([]string, 0) for { ip, _, err := reader.readline() if err != nil { if err == io.eof { break } logger.fatalf("failed to read ip range file, err:%s", err) } t.logf("ip:%s", *(*string)(unsafe.pointer(&ip))) ranges = append(ranges, *(*string)(unsafe.pointer(&ip))) } t.logf("%v", ranges) }
Ergebnis:
task_test.go:71: ip:1.1.1.0/24 task_test.go:71: ip:1.1.2.0/24 task_test.go:71: ip:2.2.1.0/24 task_test.go:71: ip:2.2.2.0/24 task_test.go:75: [2.2.2.0/24 1.1.2.0/24 2.2.1.0/24 2.2.2.0/24]
Warum wurde 1.1.1.0/24 in 2.2.2.0/24 geändert?
Veränderung
*(*string)(unsafe.Pointer(&ip))
in string(ip) funktioniert es
Während Sie also den Slice-Header als String-Header uminterpretieren, ist die Art und Weise, wie Sie es tun, absolut verrückt und es ist nicht garantiert, dass es funktioniert, aber das verursacht nur indirektdas Problem. p>
Das eigentliche Problem besteht darin, dass Sie einen Zeiger auf den bufio/Reader.ReadLine()
Rückgabewert beibehalten, in der Dokumentation der Methode jedoch steht: „Der zurückgegebene Puffer ist nur bis zum nächsten Aufruf von ReadLine gültig. Dies bedeutet, dass der Leser diesen Speicher später wiederverwenden kann.“ Das ist, was los ist.
Wenn Sie die Konvertierung richtig durchführen string(ip)
, kopiert Go den Inhalt des Puffers in eine neu erstellte Zeichenfolge, die auch in Zukunft gültig ist. Wenn Sie jedoch das Slice-Wortspiel in die Zeichenfolge eingeben, behalten Sie genau denselben Zeiger, der nicht mehr funktioniert, sobald der Reader seinen Puffer wieder auffüllt.
Wenn Sie sich dafür entscheiden, Pointer-Spoofing als Performance-Hack zu verwenden, um Kopien und Zuweisungen zu vermeiden, ist das schade. Die Leseschnittstelle zwingt Sie ohnehin dazu, die Daten zu kopieren, daher sollten Sie einfach string()
verwenden.
Das obige ist der detaillierte Inhalt vonWarum *(*string)(unsafe.Pointer(&b)) nicht mit bufio.Reader funktioniert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!