Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapa jenis rentetan Golang tidak boleh diubah suai?

Mengapa jenis rentetan Golang tidak boleh diubah suai?

藏色散人
藏色散人ke hadapan
2022-11-21 17:34:401557semak imbas

Artikel ini diperkenalkan oleh ruangan tutorial golang untuk memperkenalkan kepada anda isu pengubahsuaian jenis rentetan dalam golang Anda mungkin tertanya-tanya Adalah perkara biasa untuk kita mengubah suai rentetan dalam pembangunan harian anda mendengar ini? Bagaimana dengan rentetan dalam Go yang tidak boleh diubah suai? Berikut akan diterangkan secara terperinci dengan contoh-contoh semoga dapat membantu rakan-rakan yang memerlukan!

Apabila anda bersentuhan dengan bahasa seperti Go, anda mungkin sering mendengar ayat ini. Anda mungkin tertanya-tanya tentang hakikat bahawa rentetan tidak boleh diubah suai Adalah perkara biasa bagi kita untuk mengubah suai rentetan dalam pembangunan harian Mengapa kita mengatakan bahawa rentetan dalam Go tidak boleh diubah suai.

Artikel ini akan menunjukkan kepada anda melalui kes praktikal mengapa rentetan dalam Go tidak boleh diubah suai.

Sebelum menunjukkan masalah ini, mari kita berikan demonstrasi kasar tentang pengetahuan asas jenis rentetan, supaya semua orang dapat memahami masalah ini dengan lebih lanjut.

Takrifan rentetan

Rentetan ialah jenis data yang digunakan untuk mewakili aksara. Apabila menggunakan, gunakan " " untuk menyertakan kandungan aksara. Contohnya, bentuk berikut:

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

Dalam Go, rentetan biasanya ditakrifkan dalam tiga cara:

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

Takrifan rentetan juga boleh dalam bait. Kaedah yang disenaraikan di sini adalah yang paling biasa.

Komposisi rentetan

String dalam Go mematuhi standard Unicode dan dikodkan dalam UTF-8. Lapisan bawah rentetan sebenarnya terdiri daripada bait (akan diterangkan secara terperinci kemudian). Gunakan contoh berikut untuk mencetak dan melihat kandungan bait tertentu:

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

Kandungan yang dicetak oleh kod di atas ialah kod bait yang diwakili oleh setiap aksara.

String tidak boleh diubah suai

Melalui demonstrasi kasar di atas, kami mempunyai pemahaman asas tentang rentetan. Bagi rentetan yang tidak boleh diubah suai, anda mungkin tertanya-tanya Ia adalah perkara biasa bagi kami untuk menetapkan semula rentetan dalam pembangunan harian Mengapa kami mengatakan bahawa rentetan dalam Go tidak boleh diubah suai?

Malah, saya ingin membetulkan pernyataan ini di sini Mengubah suai rentetan tidak sama dengan menugaskannya semula. Kaedah yang biasa digunakan dalam pembangunan sebenarnya adalah konsep penugasan semula.

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

Kita sering mendengar bahawa ia tidak boleh diubah suai, tetapi ia sebenarnya merujuk kepada cara kedua kod di atas. Dan jika diubah suai dengan cara ini, ralat akan dilaporkan: :cannot assign to s [0] (value of type byte)

Kembali kepada topik, kenapa rentetan dalam Go tidak boleh diubah suai dengan melanggan?

Ini kerana struktur data rentetan dalam Go ialah struktur yang terdiri daripada penuding dan panjang Potongan yang ditunjuk oleh penuding ialah nilai rentetan sebenar. Kod sumber dalam Go mempunyai definisi ini:

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

Mengapa jenis rentetan Golang tidak boleh diubah suai?

Ia adalah tepat kerana lapisan bawah ialah kepingan jenis [] bait, apabila kami menggunakan subskrip untuk mengubah suai nilai , ini Apabila menetapkan kandungan aksara kepada jenis bait, ia pasti tidak dibenarkan. Tetapi kita boleh mengakses nilai bait yang sepadan melalui langganan.

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

Jadi apa yang perlu kita lakukan jika kita mahu mengubah suai nilai melalui langganan? Pada masa ini, anda perlu mentakrifkannya melalui penghirisan dan kemudian menukarnya menjadi rentetan.

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!

Penugasan rentetan

Di atas menganalisis mengapa rentetan tidak boleh diberikan menggunakan subskrip Mari kita kembali dan menjawab kaedah tugasan dalam pembangunan harian.

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

Jadi mengapa nilai rentetan boleh ditetapkan semula dalam senario ini?

Ini kerana di bahagian bawah Go, sekeping jenis [] bait {} sebenarnya baru dibuat dan penunjuk dalam pembolehubah s menghala ke alamat ruang memori baharu (iaitu, Hello Go! di sini! Ruang memori Hello World! yang asal akan dituntut semula dengan mekanisme pengumpulan sampah.

Mengapa jenis rentetan Golang tidak boleh diubah suai?

Mengapa ia direka bentuk seperti ini

Mungkin semua orang akan mempertimbangkan mengapa rentetan biasa sangat rumit untuk mereka bentuk dan perlu menggunakan penunjuk. Saya belum menemui sebarang dokumentasi rasmi lagi

Tekaan peribadi ialah apabila menghadapi watak yang sangat panjang, ini menjadikan rentetan sangat ringan dan boleh dipindahkan dengan mudah tanpa perlu risau tentang penyalinan memori. Walaupun dalam Go, sama ada ia adalah jenis rujukan atau parameter jenis nilai lulus, ia diluluskan oleh nilai. Tetapi penunjuk jelas lebih menjimatkan memori daripada lulus nilai.

Atas ialah kandungan terperinci Mengapa jenis rentetan Golang tidak boleh diubah suai?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:learnku.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam