12. String
String adalah nilai yang paling sering kamu cetak. Bab 07 menunjukkan
dua cara menulisnya: di antara tanda kutip ganda,
"seperti ini", dan di antara backtick,
`seperti ini`. Bab ini membahas apa yang disediakan Go
secara langsung untuk string: menggabungkan, mengukur, membaca satu
posisi, memotong sebagian, dan menulis karakter khusus.
Menggabungkan string dengan
+
Kamu bisa menggabungkan dua string dengan + (operator
concatenation). Hasilnya satu string baru dengan string
kedua menempel di akhir string pertama:
first := "Hello, "
second := "world!"
fmt.Println(first + second) // Hello, world!Variabel aslinya tidak berubah — + membangun string
baru.
+ di Go tidak mengubah angka menjadi string. Menambahkan
angka ke string adalah error kompilasi:
level := 7
fmt.Println("Level " + level)invalid operation: "Level " + level (mismatched types untyped string and int)
Untuk sekarang, perbaikannya adalah fmt.Printf dari Bab
09, yang menerima angka secara langsung:
level := 7
fmt.Printf("Level %d complete\n", level) // Level 7 completeBab 14 menunjukkan cara mengubah angka menjadi string, kalau kamu membutuhkannya.
Panjang string dengan
len
Fungsi len memberikan panjang sebuah string:
fmt.Println(len("hello")) // 5
fmt.Println(len("")) // 0
greeting := "Welcome"
fmt.Println(len(greeting)) // 7Gunakan len setiap kali kamu butuh panjang string —
untuk menengahkan teks, memeriksa panjang input, atau membuat
border.
Buka exercises/12/01-length.go. Tambahkan baris yang
mencetak panjang namamu sendiri.
String adalah byte
Bagian sebelumnya belum menyebutkan apa yang dihitung
len. Yang dihitung adalah byte, satuan
kecil yang dipakai komputer untuk menyimpan teks. Huruf Inggris biasa,
angka, atau spasi memakai satu byte, jadi untuk teks seperti
"hello", jumlah byte dan jumlah karakternya sama. Huruf
beraksen memakai lebih banyak:
fmt.Println(len("e")) // 1
fmt.Println(len("é")) // 2Untuk menghitung karakter dan bukan byte, gunakan
RuneCountInString dari package unicode/utf8.
Rune adalah sebutan Go untuk satu karakter:
word := "café"
fmt.Println(len(word)) // 5
fmt.Println(utf8.RuneCountInString(word)) // 4Ini butuh import kedua. Untuk mengimpor lebih dari satu package, taruh di dalam tanda kurung, satu per baris:
import (
"fmt"
"unicode/utf8"
)Program lengkapnya ada di exercises/12/03-bytes.go.
Sebagian besar teks di buku ini berupa huruf Inggris biasa, jadi sisa
Bagian 3 memakai len. Ingat saja bahwa hasilnya bisa lebih
besar daripada jumlah karakter yang kamu lihat.
Indeks
Setiap byte dalam string punya posisi, yang disebut indeks. Kurung siku membaca byte di satu posisi:
word := "dragon"
fmt.Println(word[0]) // 100Ada dua hal yang mengejutkan di sini. Indeks dimulai dari
0, bukan 1, jadi word[0] adalah posisi
pertama. Dan hasilnya bukan huruf d, melainkan
100, angka yang menyimpan d, karena indeks
memberimu sebuah byte. Untuk mendapatkan teks, gunakan slice, yang
dibahas di bagian berikutnya.
String di Go berindeks mulai dari 0. Kalau kamu menginginkan posisi
pertama, gunakan word[0], bukan word[1].
word[1] memberikan posisi kedua. Awalnya ini akan
terasa salah, tapi cepat menjadi terbiasa.
Slice
Slice dari sebuah string memberimu sebagian isinya,
sebagai string baru. Sintaksnya s[start:stop], dengan
start adalah indeks byte pertama yang kamu inginkan dan
stop adalah indeks setelah byte terakhir:
word := "dragon"
fmt.Println(word[0:3]) // dra
fmt.Println(word[3:]) // gon
fmt.Println(word[:1]) // dMenghilangkan stop berarti "sampai akhir string", dan
menghilangkan start berarti "dari awal". Jadi
word[:1] adalah huruf pertama sebagai string.
Go tidak punya indeks negatif. word[-3:] berhenti dengan
invalid argument: index -3 (constant of type int) must not be negative.
Untuk menghitung dari akhir, gunakan len:
word := "dragon"
fmt.Println(word[len(word)-3:]) // gon
fmt.Println(word[len(word)-1:]) // nMeminta posisi yang melewati akhir string adalah error yang biasanya tidak bisa ditangkap compiler, jadi terjadi saat program berjalan. Program berhenti dan mencetak pesan seperti:
panic: runtime error: slice bounds out of range [:10] with length 6
Slice menghitung byte, seperti len dan indeks. Dalam
"café", é memakai dua byte, di indeks 3 dan 4.
word[:3] memberikan caf, tapi
word[:4] memotong é menjadi dua dan program
mencetak karakter yang rusak. Untuk huruf Inggris biasa, hal ini tidak
pernah terjadi.
Buka exercises/12/02-index-and-slice.go. Sebuah variabel
menyimpan satu kata. Dengan slice, cetak huruf pertamanya saja, lalu
huruf terakhirnya saja.
String tidak bisa diubah
Kamu bisa memberi variabel string sebuah string baru, tapi kamu tidak bisa mengubah byte di dalam string:
word := "dragon"
word[0] = 'D'
fmt.Println(word)cannot assign to word[0] (neither addressable nor a map index expression)
Untuk mendapatkan versi yang berubah, bangun string baru dari potongan-potongannya dan berikan ke variabel:
word := "dragon"
word = "D" + word[1:]
fmt.Println(word) // DragonEscape sequence
Beberapa karakter sulit ditulis dalam string karena bentrok dengan
tanda baca Go. Solusinya adalah escape sequence — garis
miring terbalik \ diikuti sebuah karakter, yang diganti Go
dengan karakter khusus:
| Urutan | Hasilnya |
|---|---|
\n |
baris baru (pindah ke baris berikutnya) |
\t |
tab |
\" |
tanda kutip ganda |
\\ |
garis miring terbalik |
Tanda kutip tunggal tidak perlu di-escape di dalam tanda kutip ganda,
jadi tulis "it's". Menulis "it\'s" berhenti
dengan unknown escape.
Contoh:
fmt.Println("Line 1\nLine 2\nLine 3")
fmt.Println("Name\tLevel\tHP")
fmt.Println("She said \"hi\" and waved.")Output:
Line 1
Line 2
Line 3
Name Level HP
She said "hi" and waved.
String beberapa baris
Kalau string terdiri dari banyak baris dengan banyak tanda kutip, escape sequence jadi berantakan. String di antara backtick adalah raw string: apa pun di antara keduanya adalah isi string, termasuk baris baru dan tanda kutip, dan escape sequence tidak diganti.
poem := `
Roses are red,
Violets are blue,
"Pick a number,"
said the program to you.
`
fmt.Println(poem)Setelah dibuat, raw string hanyalah string biasa — dengan cara
penulisan yang lebih mudah. String ini diawali dan diakhiri baris baru,
karena backtick-nya ada di baris sendiri. Contoh-contoh ini ada di
exercises/12/04-escapes.go.
Karena \n tidak diganti dalam raw string,
`a\nb` mencetak empat karakter a\nb dalam satu
baris. Ini membuat backtick praktis untuk teks dengan banyak garis
miring terbalik, seperti path Windows.
PR
Soal 1 — Inisial
Buka exercises/12/homework/01-initials.go. Dua variabel
menyimpan nama depan dan nama belakang. Dengan slice, cetak inisial
orang itu, seperti K.R. untuk "Keiko Raharja".
Soal 2 — Baris stat
Buka exercises/12/homework/02-stat-line.go. Tiga
variabel dideklarasikan di bagian atas: string name, int level, int hp.
Dengan fmt.Printf, cetak satu baris persis dalam bentuk
ini:
Keiko Lv 7 HP 95
Label (Lv, HP) dan jarak antar bagian
adalah spasi biasa di dalam string yang kamu berikan ke
fmt.Printf.
Soal 3 — Puisi tiga baris dalam satu panggilan
Buka exercises/12/homework/03-three-line-poem.go. Cetak
puisi tiga baris dengan tepat satu panggilan
fmt.Println. Pergantian barisnya harus berasal dari
\n di dalam string. Tambahkan komentar //
setelah panggilan itu yang menjelaskan mengapa satu panggilan bisa
menghasilkan tiga baris.
Tantangan — Huruf terakhir
Buka exercises/12/homework/04-last-letters.go. Sebuah
variabel menyimpan satu kata. Dengan slice dan len, cetak
tiga karakter terakhirnya, lalu cetak panjangnya. Buat supaya berfungsi
untuk kata apa pun yang terdiri dari huruf biasa, minimal tiga huruf,
tanpa menghitung manual.
Stuck atau sudah selesai? Buka halaman solusi PR.