В этой статье я покажу вам, как формировать строки и работать с ними в Go. Как и в большинстве современных языков, большая часть функциональных возможностей строкового типа данных обеспечивается библиотекой или, в случае Go, пакетом. Этот пакет называется strings
, и я продемонстрирую несколько функций из этого пакета.
Строковый тип данных
Строки Go - это неизменяемые последовательности байтов. Неизменяемость означает, что после создания строка не может быть изменена, хотя, если строка хранится в переменной, эту переменную можно изменить.
Строки формируются путем помещения байтов, которые вы хотите рассматривать как строку, между двойными кавычками. Сформированная таким образом строка называется строковым литералом, который можно использовать в присвоении или в качестве аргумента функции.
Вот несколько примеров строковых переменных и строковых литералов:
name := "Dennis Ritchie" var greeting string = "Hello, world!"
В следующем разделе я продемонстрирую, что значит неизменяемость строки.
Основные операции со строками
Первая операция, которую я продемонстрирую, - это функция len. Эта функция возвращает количество символов в строке. Вот пример:
func main() { greeting := "Hello, world!" fmt.Printf("The length of greeting is %d.\n", len(greeting)) }
Строки Go индексируются как массивы и как срезы. Я могу отобразить каждый байт строки, используя индексированный цикл for
(вы также можете использовать функцию диапазона):
func main() { greeting := "Hello, world!" for i:=0; i<len(greeting); i++ { fmt.Println(greeting[i]) } }
Позже я покажу вам, как преобразовать байт в буквенный символ.
Несмотря на то, что вы можете получить доступ к каждому байту строки через его индекс, вы не можете изменить байт таким образом:
greeting[1] = "E"
Это вызывает панику и демонстрирует неизменность строк в Go.
Я могу разбить нить на части, разрезая нить по кусочкам:
func main() { greeting := "Hello, world!" fmt.Println(greeting[0:5]) // displays Hello }
Все разные способы работы со срезами работают со строками.
Несколько строк можно «склеить» вместе с помощью конкатенации. Оператор конкатенации Go - +
. Вот пример:
func main() { first := "Ken" last := "Thompson" full := first + " " + last fmt.Println(full) // displays Ken Thompson }
Как и в других языках, Go имеет специальные последовательности байтовых символов, которые можно встраивать в строки. Эти последовательности аналогичны последовательностям C и C ++, например \n
для новой строки и \t
для табуляции.
Пакет строк
Большая часть функций, необходимых для работы со строками, находится в пакете strings
. В этом разделе я расскажу о некоторых функциях этого пакета.
Первая функция, которую мы рассмотрим, - contains
. Эта логическая функция проверяет, содержит ли строка указанную подстроку. Вот пример:
package main import ( "fmt" "strings" ) func main() { address := "3000 W. Scenic Drive" if strings.Contains(address, "Scenic") { fmt.Print("Located on Scenic Drive") } else { fmt.Print("Located somewhere else.") } }
Следующая функция, которую я рассмотрю, - это count
. Эта функция возвращает количество вхождений указанной подстроки в строку. Вот как это работает:
package main import ( "fmt" "strings" ) func main() { s := "now is the time for all good people" os := strings.Count(s, "o") fmt.Println(s) fmt.Printf("There are %d o's in the string.\n", os) }
Далее идет функция fields
. Эта функция разбивает строку вокруг последовательности из одного или нескольких символов пробела, возвращая часть оставшихся подстрок. Пример этой функции показан ниже:
package main import ( "fmt" "strings" ) func main() { s := " now is the time for all good people" words := strings.Fields(s) fmt.Println(words) }
Функция index
возвращает позицию индекса подстроки в строке или -1
, если подстрока не найдена в строке. Вот программа, которая использует эту функцию:
package main import ( "fmt" "strings" ) func main() { s := "now is the time for all good people" foundAt := strings.Index(s, "time") if foundAt > -1 { fmt.Printf("time is found at position %d in the string.\n", foundAt) } else { fmt.Println("time is not found in string.") } }
Следующая описываемая мною функция используется для объединения нескольких подстрок в одну строку. Эта функция называется join
. Первый аргумент - это фрагмент, содержащий набор строк. Второй аргумент - это разделитель, который будет помещен между каждой строкой в срезе.
Вот пример:
package main import ( "fmt" "strings" ) func main() { sl := []string{"now","is","the","time"} joined := strings.Join(sl," ") fmt.Println(joined) }
Функция repeat
повторяет строку указанное количество раз:
package main import ( "fmt" "strings" ) func main() { fmt.Println(strings.Repeat("ei", 2) + "o") // displays eieio }
Функция replace
заменит первые n вхождений подстроки другой подстрокой и вернет новую строку. Если n меньше 0, будет выполнено столько замен, сколько возможно.
В следующем примере показано, как использовать функцию для выполнения только одной замены в строке:
package main import ( "fmt" "strings" ) func main() { misspellings := "recieve decieve reciever deciever believe" fmt.Println(misspellings) count := 1 spellings := strings.Replace(misspellings, "cie", "cei", count) fmt.Println(spellings) }
Если вы хотите заменить все подстроки в строке другой подстрокой, используйте функцию ReplaceAll
. Вот как это работает:
package main import ( "fmt" "strings" ) func main() { misspellings := "recieve decieve reciever deciever believe" fmt.Println(misspellings) spellings := strings.ReplaceAll(misspellings, "cie", "cei") fmt.Println(spellings) }
Следующая функция, которую я собираюсь продемонстрировать, - это функция, сестра join
. Функция split
принимает строку и разделитель и возвращает фрагмент, содержащий весь текст между разделителями. Если строка равна “Meredith,Allison,Mason”
, а разделитель равен, то возвращаемый фрагмент - [Meredith Allison Mason]
. Вот код для этого:
package main import ( "fmt" "strings" ) func main() { siblings := "Meredith,Allison,Mason" splitUp := strings.Split(siblings, ",") fmt.Println(splitUp) }
Следующие две функции можно использовать для изменения регистра строки. ToLower
заменяет строку на нижний регистр, а ToUpper
изменяет регистр на верхний регистр. Вот пример:
package main import ( "fmt" "strings" ) func main() { s := "I'M YELLING" fmt.Println(strings.ToLower(s)) s = "i'm whispering" fmt.Println(strings.ToUpper(s)) }
Последний пример, который я продемонстрирую, - это функция TrimSpace
, которая обрезает все пробелы от начала и до конца строки. Вот как работает эта функция:
package main import ( "fmt" "strings" ) func main() { name := " Dennis Ritchie " fmt.Println(name) name = strings.TrimSpace(name) fmt.Println(name) }
Это всего лишь несколько примеров функций из пакета strings, и вам следует просмотреть документ Go в пакете, чтобы увидеть полный список.
Преобразования строк
Очень кратко отмечу еще один пакет - strconv
. Этот пакет содержит функции для преобразования строк в числа и числа в строки, а также других преобразований.
Функция Itoa
преобразует целое число в строку. Вот пример его использования:
package main import ( "fmt" "strconv" ) func main() { fmt.Print("Hello, Agent " + strconv.Itoa(99) + ".") }
Функция Atoi
преобразует строку в целое число. Он также возвращает объект ошибки, который необходимо обработать при вызове функции, как вы можете видеть в примере ниже:
package main import ( "fmt" "strconv" ) func main() { number1, err := strconv.Atoi("1") number2, err1 := strconv.Atoi("2") result := number1 + number2 if err == nil && err1 == nil { fmt.Printf("%d + %d = %d.\n", number1, number2, result) } }
В пакете strconv
есть еще несколько функций, но это две из тех, которые вы будете использовать чаще всего.
Есть еще два пакета, которые относятся к строкам Go, байтам и Unicode, но я не собираюсь их здесь описывать. Если вам интересны эти пакеты, обратитесь к документации Go.
Строки и символы
Вы должны заметить, что в Go нет типа char. Для этой цели используется тип byte
, как мы видели в начале этой статьи, когда я перебирал строку, используя индексированный цикл for. В конце статьи я покажу вам, как преобразовать байт в строку с помощью функции Printf
:
func main() { greeting := "Hello, world!" for i:=0; i<len(greeting); i++ { fmt.Printf("%c\n", greeting[i]) } }
Спецификация формата% c изменит байт на символ, чтобы отобразить его для вывода.
Го и струнные
В Go есть хорошая современная реализация строк. В этой статье я рассмотрел то, что считаю наиболее важным аспектом использования строк в Go, но не все. Я особенно избегал говорить о том, как Go использует Unicode при реализации строк. Если вы хотите узнать об этом больше, я предлагаю прочитать книгу Алана Донована и Брайана Кернигана Язык программирования Go.
Спасибо за чтение, напишите мне с комментариями и предложениями.