День 04 · Чужой код и готовые функции · страница 2 из 7

Пакет strings

Вместе с компилятором Go приходит стандартная библиотека — сотни пакетов с готовыми функциями, они уже лежат в /usr/local/go. Пакет fmt — один из них; сегодня добавятся strings, math для округления, strconv для превращения чисел в строки и unicode/utf8 для подсчёта символов.


Несколько пакетов в import

Код для чтения · разбираем, набирать не нужно
import (
	"fmt"
	"strings"
)

По пакету на строку, каждый в кавычках, без запятых. Порядок неважен: gofmt — а в VS Code Ctrl+S — расставит пакеты по алфавиту сам, но добавлять и удалять их не будет, это ваша работа.


Ситуация: выгрузка от поставщика

Поставщик прислал список товаров: названия то большими буквами, то маленькими, с лишними пробелами по краям, разделители разные. Прежде чем считать, строки надо привести в порядок и научиться задавать им вопросы: «это срочный заказ?», «сколько здесь стульев?».

Восемь функций strings, которых хватит на весь первый блок:

Код для чтения · разбираем, набирать не нужно
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.ToUpper("tk-4821"))
	fmt.Println(strings.ToLower("СКЛАД Север"))
	fmt.Println("[" + strings.TrimSpace("   Казань \n") + "]")
	fmt.Println(strings.Repeat("-", 12))
	fmt.Println(strings.Contains("срочная доставка", "срочн"))
	fmt.Println(strings.HasPrefix("SKU-4821", "SKU-"))
	fmt.Println(strings.HasPrefix("sku-4821", "SKU-"))
	fmt.Println(strings.ReplaceAll("стол; стул; лампа", "; ", ", "))
	fmt.Println(strings.Count("стол, стул, стул", "стул"))
	fmt.Println(strings.Count("Стул, стул", "стул"))
}

Что увидите:

Вывод · это печатает программа, набирать не нужно
TK-4821
склад север
[Казань]
------------
true
true
false
стол, стул, лампа
2
1

Как это читать

Функция Что делает Тип результата
strings.ToUpper(s) все буквы в верхний регистр, кириллицу тоже string
strings.ToLower(s) все буквы в нижний регистр string
strings.TrimSpace(s) убирает пробелы и переводы строк по краям, внутри не трогает string
strings.Repeat(s, n) строка s, повторённая n раз string
strings.Contains(s, part) есть ли part где-нибудь внутри s bool
strings.HasPrefix(s, start) начинается ли s с start bool
strings.ReplaceAll(s, old, new) заменяет все вхождения old на new string
strings.Count(s, part) сколько раз part встречается в s int

Тип результата разный. Contains и HasPrefix отвечают bool, Count — целым числом, остальные — строкой. От типа зависит, что делать с результатом дальше: строку можно склеить с другой через +, а число и bool — нет.

Регистр важен. HasPrefix("sku-4821", "SKU-") — false: маленькая s и большая S — разные символы. Последний Count нашёл один стул, а не два: Стул с большой буквы не совпал с стул. Если регистр неважен, сначала приведите строку к одному регистру: strings.Count(strings.ToLower(line), "стул").


Что может пойти не так

Что видите Что это значит Что делать
./main.go:7:14: undefined: strings пакет используется, но не подключён добавить "strings" в import
./main.go:5:2: "strings" imported and not used подключили, но не вызвали ни одной функции пакета убрать из import или вызвать то, ради чего подключали
undefined: strings.Upper в пакете нет функции с таким именем точное имя подскажет go doc strings — пятая страница
undefined: strings.toUpper (but have ToUpper) имя с маленькой буквы функции пакетов — с большой: ToUpper
invalid operation: "Стульев: " + strings.Count(order, "стул") (mismatched types untyped string and int) Count вернул число, а склеивать через + можно только строки превратить число в строку — strconv.Itoa, следующая страница
Count вернул меньше, чем видно глазами регистр не совпал или в искомом лишний пробел ToLower перед поиском

Попробуйте сейчас: восемь функций и две поломки.

Цель: посчитать стулья без учёта регистра и увидеть сообщения о пропавшем импорте и неверном имени функции.

Наберите в черновике программу с восемью функциями:

✎ Наберите в файл scratch/main.go
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.ToUpper("tk-4821"))
	fmt.Println(strings.ToLower("СКЛАД Север"))
	fmt.Println("[" + strings.TrimSpace("   Казань \n") + "]")
	fmt.Println(strings.Repeat("-", 12))
	fmt.Println(strings.Contains("срочная доставка", "срочн"))
	fmt.Println(strings.HasPrefix("SKU-4821", "SKU-"))
	fmt.Println(strings.HasPrefix("sku-4821", "SKU-"))
	fmt.Println(strings.ReplaceAll("стол; стул; лампа", "; ", ", "))
	fmt.Println(strings.Count("стол, стул, стул", "стул"))
	fmt.Println(strings.Count("Стул, стул", "стул"))
}
▶ Выполните
cd ~/gocourse/day04/scratch
go run .

Вывод — как в «Что увидите». Потом:

  1. Добавьте строку, которая печатает число стульев в "Стул, стул" без учёта регистра. Должно получиться 2.
  2. Удалите "strings" из import, сохраните и запустите. Сам импорт не вернётся — ни при Ctrl+S, ни при go run .. Компилятор выдаст десять одинаковых undefined: strings — по одному на вызов — и остановится на too many errors: больше десяти он не показывает. Причина у всех одна. Верните импорт сами.
  3. Замените ToUpper на Upper и прочитайте, что скажет компилятор.

Готово, когда: добавленная строка печатает 2; без импорта вы видели undefined: strings и too many errors, с Upper — undefined: strings.Upper; импорт и ToUpper возвращены, новые сообщения — в ~/errors.md (пункт errors).


Попробуйте сейчас: что выведет, не запуская.

Цель: предсказать вывод по коду и отправить его.

Не запуская, предскажите вывод:

Код для чтения · разбираем, набирать не нужно
package main

import (
	"fmt"
	"strings"
)

func main() {
	city := "  Казань  "
	fmt.Println(strings.HasPrefix(city, "Каз"), strings.Count(city, " "))
}

Пробелов в city — два в начале и два в конце. Отправьте строку вывода целиком:

▶ Выполните · выделенное замените своим
course answer day04.q2 ВАШ_ОТВЕТ

Готово, когда: course answer ответил Принято: day04.q2 = … (пункт проверки q2).


Дальше: округление и числа в строках — course next