Heim  >  Artikel  >  Backend-Entwicklung  >  Warum kann der Golang-String-Typ nicht geändert werden?

Warum kann der Golang-String-Typ nicht geändert werden?

藏色散人
藏色散人nach vorne
2022-11-21 17:34:401492Durchsuche

Dieser Artikel wurde von der Kolumne golang-Tutorial geschrieben, um Sie in das Problem der Zeichenfolgentypänderung in Golang einzuführen. Sie fragen sich möglicherweise, dass es für uns normal ist, Zeichenfolgen in Go zu ändern ? Können Sie keine Änderungen vornehmen? Das Folgende wird anhand von Beispielen ausführlich erläutert. Ich hoffe, dass es Freunden in Not hilfreich sein wird!

Wenn man mit einer Sprache wie Go in Kontakt kommt, hört man diesen Satz vielleicht oft. Sie fragen sich vielleicht, dass Strings in der täglichen Entwicklung nicht geändert werden können. Warum sagen wir, dass Strings in Go nicht geändert werden können?

Dieser Artikel zeigt Ihnen anhand eines praktischen Falls, warum Zeichenfolgen in Go nicht geändert werden können.

Bevor wir dieses Problem demonstrieren, lassen Sie uns zunächst eine grobe Demonstration des Grundwissens über String-Typen geben, damit jeder das Problem besser verstehen kann.

String-Definition

String ist ein Datentyp, der zur Darstellung von Zeichen verwendet wird. Verwenden Sie bei der Verwendung „ “, um den Zeicheninhalt einzuschließen. Zum Beispiel die folgende Form:

package main
import "fmt"
func main() {
    var str string = "Hello World!"
}

In Go werden Zeichenfolgen normalerweise auf drei Arten definiert:

// 第一种(全量定义)
var 变量名称 string = "字符串内容"
// 类型推导
var 变量名称 = "字符串内容"
// 短标记(只适用于局部变量)
变量名称 := "字符串内容"

Die Definition von Zeichenfolgen kann tatsächlich in Bytes erfolgen. Die hier aufgeführten Methoden sind die gebräuchlichsten.

Zusammensetzung von Strings

Strings in Go entsprechen dem Unicode-Standard und sind in UTF-8 codiert. Die unterste Schicht der Zeichenfolge besteht tatsächlich aus Bytes (wird später ausführlich erläutert). Verwenden Sie das folgende Beispiel, um den spezifischen Byte-Inhalt auszudrucken und anzuzeigen:

s := "Hello World!"
for _, v := range s {
    fmt.Print(v)
    fmt.Print("\t")
}
// 72 101 108 108 111 32 87 111 114 108 100 33

Der vom obigen Code gedruckte Inhalt ist der Bytecode, der durch jedes Zeichen dargestellt wird.

Strings können nicht geändert werden

Durch die obige grobe Demonstration haben wir ein grundlegendes Verständnis von Strings erlangt. Was Zeichenfolgen betrifft, die nicht geändert werden können, fragen Sie sich möglicherweise: Es ist normal, dass wir Zeichenfolgen in der täglichen Entwicklung neu zuweisen.

Tatsächlich möchte ich diese Aussage hier korrigieren. Die in der Entwicklung häufig verwendete Methode ist eigentlich ein Konzept der Neuzuweisung.

str := "Hello World!"
// 重新赋值
str = "Hello Go!"
// 字符串修改
str[0] = "I"

Das häufig gehörte Sprichwort, dass es nicht geändert werden kann, bezieht sich tatsächlich auf die zweite Möglichkeit des obigen Codes. Und wenn es auf diese Weise geändert wird, wird ein Fehler gemeldet: :kann nicht zu s [0] (Wert vom Typ Byte) zugewiesen werden

Zurück zum Thema: Warum können Zeichenfolgen in Go nicht durch Subskription geändert werden?

Das liegt daran, dass die String-Datenstruktur in Go eine Struktur ist, die aus einem Zeiger und einer Länge besteht. Das Slice, auf das der Zeiger zeigt, ist der tatsächliche String-Wert. Der Quellcode in Go hat eine solche Definition:

type stringStruct struct {
    str unsafe.Pointer // 指向一个byte类型的切片指针
    len int // 字符串的长度
}

Warum kann der Golang-String-Typ nicht geändert werden?

Dies liegt genau daran, dass die unterste Ebene ein Segment vom Bytetyp [] ist. Wenn wir Indizes verwenden, um den Wert zu ändern, weisen wir dem Bytetyp einen Zeicheninhalt zu muss Nicht erlaubt sein. Wir können jedoch durch Subskription auf den entsprechenden Bytewert zugreifen.

fmt.Println(s[0]) // output:72

Was sollen wir also tun, wenn wir den Wert durch Abonnements ändern möchten? Zu diesem Zeitpunkt müssen Sie es durch Slicing definieren und dann in eine Zeichenfolge konvertieren.

package main
import (  
    "fmt"
)
func main() {  
     s1 := []byte{72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33}
    fmt.Println(string(s1))
    // 将"H"修改为l
    s1[0] = 108
    fmt.Println(string(s1))
}
// output:
Hello World!
lello World!

Zuweisung von Zeichenfolgen

Oben wird analysiert, warum Zeichenfolgen nicht mithilfe von Indizes zugewiesen werden können. Gehen wir zurück und erklären wir die Zuweisungsmethoden in der täglichen Entwicklung.

package main
import (  
    "fmt"
)
func main() {
    // 声明一个字符串,并给与初始值
    s := "Hello World!"
    // 对变量 s 进行重新赋值
    s := "Hello Go!"
}

Warum können dann in diesem Szenario Zeichenfolgenwerte neu zugewiesen werden?

Das liegt daran, dass am Ende von Go tatsächlich ein Slice vom Typ [] Byte {} neu erstellt wird, das den Zeiger in der Variablen s auf die neue Speicherplatzadresse zeigt (das heißt hier Hallo Go!). Der ursprüngliche Hello World!-Speicherplatz wird mit dem Garbage-Collection-Mechanismus zurückgewonnen.

Warum kann der Golang-String-Typ nicht geändert werden?

Warum ist es so gestaltet?

Vielleicht wird jeder darüber nachdenken, warum ein gewöhnlicher String so kompliziert zu entwerfen ist und Zeiger verwenden muss. Ich habe derzeit keine offizielle Dokumentation gefunden.

Meine persönliche Vermutung ist, dass die Zeichenfolge bei sehr langen Zeichen sehr leicht ist und problemlos übertragen werden kann, ohne sich Gedanken über das Kopieren aus dem Speicher machen zu müssen. Obwohl in Go die Parameterübergabe unabhängig davon erfolgt, ob es sich um einen Referenztyp oder einen Werttyp handelt, erfolgt die Übergabe als Wert. Aber Zeiger sind offensichtlich speichereffizienter als die Wertübergabe.

Das obige ist der detaillierte Inhalt vonWarum kann der Golang-String-Typ nicht geändert werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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