Skip to content

String Go

Di Go string pada dasarnya adalah urutan byte yang tidak dapat diubah hanya baca (byte sequence) di sini "urutan byte" mengacu pada data底层 string terdiri dari serangkaian byte yang disusun secara berurutan byte-byte ini menempati ruang memori yang berkelanjutan.

Literal

Sebelumnya sudah disebutkan string memiliki dua cara ekspresi literal dibagi menjadi string biasa dan string asli.

String Biasa

String biasa dinyatakan dengan tanda kutip ganda "" mendukung escape tidak mendukung penulisan multi baris berikut adalah beberapa string biasa

go
"Ini adalah string biasa\n"
"abcdefghijlmn\nopqrst\t\\uvwxyz"
Ini adalah string biasa
abcdefghijlmn
opqrst  \uvwxyz

String Asli

String asli dinyatakan dengan tanda kutip terbalik tidak mendukung escape mendukung penulisan multi baris semua karakter dalam string asli akan dikeluarkan apa adanya termasuk baris baru dan indentasi.

go
`Ini adalah string asli, baris baru
  indentasi tab, \t karakter tab tetapi tidak efektif, baris baru
  "Ini adalah string biasa"

  selesai
`
Ini adalah string asli, baris baru
        indentasi tab, \t karakter tab tetapi tidak efektif, baris baru
        "Ini adalah string biasa"

        selesai

Akses

Karena string pada dasarnya adalah urutan byte operasi indeks str[i] dirancang untuk mengembalikan byte ke-i secara sintaksis konsisten dengan slice misalnya mengakses elemen pertama string

go
func main() {
   str := "this is a string"
   fmt.Println(str[0])
}

Output adalah nilai encoding byte bukan karakter

116

Memotong string

go
func main() {
   str := "this is a string"
   fmt.Println(string(str[0:4]))
}
this

Mencoba memodifikasi elemen string

go
func main() {
   str := "this is a string"
   str[0] = 'a' // Tidak dapat dikompilasi
   fmt.Println(str)
}
main.go:7:2: cannot assign to str[0] (value of type byte)

Meskipun tidak dapat memodifikasi string tetapi dapat menimpa

go
func main() {
   str := "this is a string"
   str = "that is a string"
   fmt.Println(str)
}
that is a string

Konversi

String dapat dikonversi ke slice byte sedangkan slice byte atau urutan byte juga dapat dikonversi ke string contohnya sebagai berikut

go
func main() {
   str := "this is a string"
   // Konversi tipe eksplisit ke slice byte
   bytes := []byte(str)
   fmt.Println(bytes)
   // Konversi tipe eksplisit ke string
   fmt.Println(string(bytes))
}

Konten string adalah hanya baca tidak dapat diubah tetapi slice byte dapat dimodifikasi.

go
func main() {
  str := "this is a string"
  fmt.Println(&str)
  bytes := []byte(str)
    // Memodifikasi slice byte
  bytes = append(bytes, 96, 97, 98, 99)
    // Diberikan ke string asli
  str = string(bytes)
  fmt.Println(str)
}

Setelah mengonversi string ke slice byte keduanya tidak ada hubungan sama sekali karena Go akan mengalokasikan ruang memori baru untuk slice byte lalu menyalin memori string ke sana memodifikasi slice byte tidak akan menghasilkan dampak apa pun pada string asli ini dilakukan untuk keamanan memori.

Dalam situasi ini jika string atau slice byte yang akan dikonversi besar maka overhead performa akan sangat tinggi. Tetapi Anda juga dapat melalui pustaka unsafe untuk mengimplementasikan konversi tanpa copy tetapi masalah keamanan di baliknya harus ditanggung sendiri misalnya contoh di bawah ini alamat b1 dan s1 sama.

go
func main() {
  s1 := "hello world"
  b1 := unsafe.Slice(unsafe.StringData(s1), len(s1))
  fmt.Printf("%p %p", unsafe.StringData(s1), unsafe.SliceData(b1))
}
0xe27bb2 0xe27bb2

Panjang

Panjang string sebenarnya bukan jumlah karakter tetapi panjang urutan byte. Hanya saja sebagian besar waktu kita memproses karakter ASCII setiap karakter kebetulan dapat dinyatakan dengan satu byte jadi panjang byte dengan jumlah karakter kebetulan sama. Meminta panjang string menggunakan fungsi built-in len contohnya sebagai berikut

go
func main() {
   str := "this is a string" // Terlihat panjangnya 16
   str2 := "这是一个字符串" // Terlihat panjangnya 7
   fmt.Println(len(str), len(str2))
}
16 21

Terlihat string karakter China lebih pendek daripada string karakter Inggris tetapi panjang yang sebenarnya diminta lebih panjang daripada string karakter Inggris. Ini karena dalam encoding unicode satu karakter Han dalam sebagian besar situasi menempati 3 byte satu karakter Inggris hanya menempati satu byte melalui mengeluarkan elemen pertama string dapat melihat hasilnya

go
func main() {
   str := "this is a string"
   str2 := "这是一个字符串"
   fmt.Println(string(str[0]))
   fmt.Println(string(str2[0]))
   fmt.Println(string(str2[0:3]))
}
t // huruf t
è // "pecahan" (byte pertama) dari satu karakter China nilai encodingnya kebetulan sama dengan nilai encoding karakter Italia è
这 // Karakter Han China

Copy

Mirip dengan cara copy array slice copy string sebenarnya adalah copy slice byte menggunakan fungsi built-in copy

go
func main() {
   var dst, src string
   src = "this is a string"
   desBytes := make([]byte, len(src))
   copy(desBytes, src)
   dst = string(desBytes)
   fmt.Println(src, dst)
}

Juga dapat menggunakan fungsi strings.clone tetapi sebenarnya implementasi internalnya hampir sama

go
func main() {
   var dst, src string
   src = "this is a string"
   dst = strings.Clone(src)
   fmt.Println(src, dst)
}

Penggabungan

Penggabungan string menggunakan operator +

go
func main() {
   str := "this is a string"
   str = str + " that is a int"
   fmt.Println(str)
}

Juga dapat dikonversi ke slice byte lalu menambahkan elemen

go
func main() {
   str := "this is a string"
   bytes := []byte(str)
   bytes = append(bytes, "that is a int"...)
   str = string(bytes)
   fmt.Println(str)
}

Kedua cara penggabungan di atas performanya sangat buruk umumnya dapat digunakan tetapi jika memiliki persyaratan lebih tinggi untuk performa dapat menggunakan strings.Builder

go
func main() {
   builder := strings.Builder{}
   builder.WriteString("this is a string ")
   builder.WriteString("that is a int")
   fmt.Println(builder.String())
}
this is a string that is a int

Iterasi

Di awal artikel ini sudah disebutkan string di Go adalah slice byte yang hanya baca yaitu unit penyusun string adalah byte bukan karakter. Situasi ini sering ditemui saat melakukan iterasi pada string misalnya kode di bawah ini

go
func main() {
  str := "hello world!"
  for i := 0; i < len(str); i++ {
    fmt.Printf("%d,%x,%s\n", str[i], str[i], string(str[i]))
  }
}

Contoh ini masing-masing mengeluarkan bentuk desimal dan heksadesimal dari byte.

104,68,h
101,65,e
108,6c,l
108,6c,l
111,6f,o
32,20,
119,77,w
111,6f,o
114,72,r
108,6c,l
100,64,d
33,21,!

Karena karakter dalam contoh termasuk dalam karakter ASCII hanya perlu satu byte untuk menyatakan jadi hasilnya kebetulan setiap byte sesuai dengan satu karakter. Tetapi jika berisi karakter non ASCII hasilnya akan berbeda sebagai berikut

go
func main() {
  str := "hello 世界!"
  for i := 0; i < len(str); i++ {
    fmt.Printf("%d,%x,%s\n", str[i], str[i], string(str[i]))
  }
}

Biasanya satu karakter China akan menempati 3 byte jadi mungkin melihat hasil berikut

104,68,h
101,65,e
108,6c,l
108,6c,l
111,6f,o
32,20,
228,e4,ä
184,b8,¸
150,96,–
231,e7,ç
149,95,•
140,8c,Œ
33,21,!

Melakukan iterasi berdasarkan byte akan memecah karakter China ini jelas akan muncul karakter acak. String Go secara eksplisit mendukung UTF-8 untuk mengatasi situasi ini perlu menggunakan tipe rune saat menggunakan for range untuk melakukan iterasi unit iterasi defaultnya adalah rune misalnya kode di bawah ini

go
func main() {
   str := "hello 世界!"
   for _, r := range str {
      fmt.Printf("%d,%x,%s\n", r, r, string(r))
   }
}

Output adalah sebagai berikut

104,68,h
101,65,e
108,6c,l
108,6c,l
111,6f,o
32,20,
19990,4e16,世
30028,754c,界
33,21,!

rune pada dasarnya adalah alias tipe int32 rentang set karakter unicode terletak antara 0x0000 - 0x10FFFF maksimum hanya tiga byte jumlah byte maksimum encoding UTF-8 yang valid hanya 4 byte jadi menggunakan int32 untuk menyimpan adalah hal yang wajar contoh di atas mengonversi string ke []rune lalu melakukan iterasi juga sama prinsipnya sebagai berikut

go
func main() {
   str := "hello 世界!"
   runes := []rune(str)
   for i := 0; i < len(runes); i++ {
      fmt.Println(string(runes[i]))
   }
}

Juga dapat menggunakan alat di bawah paket utf8 misalnya

go
func main() {
  str := "hello 世界!"
  for i, w := 0, 0; i < len(str); i += w {
    r, width := utf8.DecodeRuneInString(str[i:])
    fmt.Println(string(r))
    w = width
  }
}

Output kedua contoh ini sama.

TIP

Tentang lebih banyak detail string dapat pergi ke Strings, bytes, runes and characters in Go untuk memahami.

Golang by www.golangdev.cn edit