Вызов функции
Сегодня день чтения: чужой код читают чаще, чем пишут свой с нуля, и большая часть этого кода — вызовы готовых функций. Свои функции будете писать в день 11.
Функция — готовое действие с именем
Одну функцию вы уже вызывали — fmt.Println. Функция — кусок кода, который кто-то написал заранее и назвал: чтобы им пользоваться, надо знать только имя, что передать и что она вернёт. func main — тоже функция, только её вызывает Go сам при запуске программы.
Ситуация: артикул большими буквами
В выгрузке поставщика артикулы записаны маленькими буквами: tk-4821, а на этикетке нужно TK-4821, и артикулов тысячи. В пакете strings есть ToUpper — «в верхний регистр».
package main
import (
"fmt"
"strings"
)
func main() {
sku := "tk-4821"
code := strings.ToUpper(sku)
fmt.Println("Артикул:", code)
fmt.Println(strings.Repeat("=", 16))
fmt.Println(sku)
}Пакетов теперь два, поэтому import со скобками — подробнее на следующей странице.
Что увидите:
stagiaire@lab:~/gocourse/day04/scratch$ go run .
Артикул: TK-4821
================
tk-4821Как это читать
Разберём строку code := strings.ToUpper(sku):
| Кусок | Что значит |
|---|---|
strings |
пакет, где живёт функция; он подключён в import |
. |
«из пакета strings взять…» |
ToUpper |
имя функции. С большой буквы — значит, её можно вызывать из другого пакета |
(sku) |
аргумент — что передаём функции |
code := |
результат вызова кладём в новую переменную |
Сначала Go вычисляет аргумент, потом уходит в функцию и возвращается с результатом. Результат встаёт на место вызова — как будто написано code := "TK-4821".
Последняя строка вывода — tk-4821: переменная sku не изменилась. ToUpper не переделывает строку, а возвращает новую. Нужен результат — положите его в переменную, можно в ту же: sku = strings.ToUpper(sku).
strings.Repeat("=", 16) — вызов с двумя аргументами через запятую: что повторять и сколько раз. Как узнать их порядок, не гадая, — на пятой странице.
Результат можно сразу передать дальше
Вызов можно поставить везде, где подходит значение такого типа, — даже в аргумент другого вызова.
Дальше показываем только строки из тела main — вставляйте их между { и } в scratch/main.go. С одним import "fmt" первая строка тела — шестая. Пакеты, которые вызывает фрагмент, добавьте в import сами: Ctrl+S их не добавляет.
raw := " tk-4821 "
fmt.Println("[" + strings.ToUpper(strings.TrimSpace(raw)) + "]")[TK-4821]Вложенные вызовы читаются изнутри наружу: TrimSpace даёт "tk-4821", ToUpper — "TK-4821", потом склейка, потом печать.
Попробуйте сейчас: вложенные вызовы в черновике.
Цель: увидеть, что вложенные вызовы выполняются изнутри наружу.
Наберите в черновике программу целиком — те же две строки тела
main, аimportсо скобками:✎ Наберите в файлscratch/main.gopackage main import ( "fmt" "strings" ) func main() { raw := " tk-4821 " fmt.Println("[" + strings.ToUpper(strings.TrimSpace(raw)) + "]") }▶ Выполнитеcd ~/gocourse/day04/scratch go run .Должно напечататься
[TK-4821]. Потом уберите внутренний вызов: вместоstrings.TrimSpace(raw)оставьте простоraw. Предскажите, где окажутся пробелы в скобках, и проверьте запуском.После опыта верните черновик к заготовке —
package main,import "fmt", в телеmainодна строкаfmt.Println("черновик"): номера строк в следующих фрагментах считаются от неё.Готово, когда: первый запуск напечатал
[TK-4821], предсказание пробелов сверено со вторым запуском, а черновик снова заготовка с одним"fmt"вimport.
Одни функции делают, другие отвечают
fmt.Println делает: печатает на экран. strings.ToUpper ничего не печатает и не меняет — только отвечает значением. Ответ, который никуда не положили, пропадает:
sku := "tk-4821"
strings.ToUpper(sku)
fmt.Println(sku)tk-4821Компилятор здесь молчит: вызвать функцию и выбросить результат в Go разрешено. Программа собирается и печатает не то — ошибку видно только по выводу. Это главная ловушка дня: она встретится и в label, и в fix2.
К встроенным функциям вроде len компилятор строже: строка len(sku) сама по себе не соберётся. Поставьте её вместо strings.ToUpper(sku) — пакет strings больше не вызывается, в import остаётся один "fmt":
./main.go:7:2: len(sku) (value of type int) is not usedУ strings.ToUpper выброшенный результат не поймает никто, кроме вас.
Бывают и функции с двумя результатами: strings.CutPrefix отрезает начало строки и сообщает, было ли это начало, — слева тогда две переменные через запятую. Пример в course extra 04, подробно — в день 07.
Что может пойти не так
Аргументов меньше, чем нужно — в программе из «Ситуации» из вызова strings.Repeat убрали , 16:
./main.go:12:29: not enough arguments in call to strings.Repeat
have (string)
want (string, int)have — что вы передали, want — что функция ждёт.
| Что видите | Что это значит | Что делать |
|---|---|---|
not enough arguments in call to strings.Repeat |
аргументов меньше, чем принимает функция | добавить недостающие — типы и порядок в строке want |
too many arguments in call to strings.ToUpper, ниже have (string, string), want (string) |
передан лишний аргумент | убрать лишнее |
cannot use 16 (untyped int constant) as string value in argument to strings.Repeat и сразу cannot use "=" (untyped string constant) as int value ... |
аргументы переставлены местами | порядок — как в go doc strings.Repeat |
| программа собирается, но строка не поменялась | результат ToUpper выброшен молча |
sku = strings.ToUpper(sku) |
Попробуйте сейчас: три поломки вызова.
Цель: увидеть сообщения о числе и порядке аргументов и молча выброшенный результат, а сами сообщения записать в словарик.
Откройте папку дня в VS Code и наберите в черновик программу из «Ситуации»:
▶ Выполнитеcd ~/gocourse/day04 code .✎ Наберите в файлscratch/main.gopackage main import ( "fmt" "strings" ) func main() { sku := "tk-4821" code := strings.ToUpper(sku) fmt.Println("Артикул:", code) fmt.Println(strings.Repeat("=", 16)) fmt.Println(sku) }▶ Выполнитеcd ~/gocourse/day04/scratch go run .Вывод — как в «Что увидите». Потом по очереди, каждый раз запуская
go run .и возвращая как было:
- Уберите
, 16изstrings.Repeat. Прочитайтеhaveиwant.- Поменяйте аргументы местами:
strings.Repeat(16, "="). Сообщений будет два — на каждый аргумент.- Замените
code := strings.ToUpper(sku)наstrings.ToUpper(sku), а в первомPrintlnвместоcodeнапечатайтеsku. Компилятор промолчит — посмотрите, что напечатается.Новые сообщения запишите в
~/errors.md, как в день 01: слева текст ошибки, тире, справа — что это значило.Готово, когда: на шаге 1 вы видели
not enough arguments…сhaveиwant, на шаге 2 — дваcannot use …, на шаге 3 программа напечаталаАртикул: tk-4821, а новые сообщения — в~/errors.md(пунктerrors).
Попробуйте сейчас: что выведет, не запуская.
Цель: предсказать вывод по коду и отправить его.
Не запуская, предскажите вывод:
Код для чтения · разбираем, набирать не нужноpackage main import ( "fmt" "strings" ) func main() { sku := "tk-4821" strings.ToUpper(sku) fmt.Println(sku, strings.Repeat("ab", 3)) }Отправьте предсказанную строку целиком:
▶ Выполните · выделенное замените своимcourse answer day04.q1 ВАШ_ОТВЕТПотом проверьте себя запуском — ту же программу в черновик:
✎ Наберите в файлscratch/main.gopackage main import ( "fmt" "strings" ) func main() { sku := "tk-4821" strings.ToUpper(sku) fmt.Println(sku, strings.Repeat("ab", 3)) }▶ Выполнитеcd ~/gocourse/day04/scratch go run .Разошлось — отправьте ответ заново, засчитывается последний.
Готово, когда:
course answerответилПринято: day04.q1 = …, а вывод совпал с отправленной строкой (пункт проверкиq1).
Дальше: пакет strings — course next