ЗАМЕР
bench/gointerface/methodsets.sh
Скрипт, которым получены числа в статье, и запись прогона. Файл читается на сборке из репозитория — это тот самый код, который запускали, а не его копия.
- Цитируется в статье
- /ru/interview/golang/interfaces
Запись прогона
У этого замера записи прогона нет — только скрипт.
Скрипт
79 строк#!/usr/bin/env bash
#
# Неявная реализация и наборы методов: что говорит КОМПИЛЯТОР.
#
# ЗАЧЕМ СКРИПТ, А НЕ ПРОГРАММА. Обе половины этой темы проверяются сборкой, а
# не запуском. «Тип реализует интерфейс, ничего об этом не объявляя» доказывается
# тем, что программа СОБИРАЕТСЯ; «метод с получателем-указателем не входит в
# набор методов значения» — тем, что не собирается, и текстом ошибки. Ни то, ни
# другое напечатать из работающей программы нельзя.
#
# ПОЧЕМУ ЭТО ВАЖНО ДЛЯ УРОКА. Аудит линии просил начинать интерфейсы с неявной
# реализации и наборов методов, а не с двух машинных слов рантайма. Здесь для
# этого есть доказательство того же сорта, что и для всего остального в линии:
# не «так устроено», а вывод инструмента.
#
# ЗАПУСК:
#
# bash bench/gointerface/methodsets.sh
set -u
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
cat > "$tmp/go.mod" <<'EOF'
module methodsets
go 1.24
EOF
echo "=== 1. РЕАЛИЗАЦИЯ БЕЗ ОБЪЯВЛЕНИЯ ==="
cat > "$tmp/ok.go" <<'EOF'
package main
import "fmt"
// Интерфейс объявлен здесь и ничего не знает о Point.
type Stringer interface{ String() string }
// Point не упоминает Stringer ни одним словом.
type Point struct{ X, Y int }
func (p Point) String() string { return fmt.Sprintf("(%d,%d)", p.X, p.Y) }
func main() {
var s Stringer = Point{1, 2}
fmt.Println("assigned:", s.String())
}
EOF
( cd "$tmp" && go run ok.go )
echo "--- exit code: $?"
echo
echo "=== 2. ПОЛУЧАТЕЛЬ-УКАЗАТЕЛЬ И НАБОР МЕТОДОВ ЗНАЧЕНИЯ ==="
cat > "$tmp/bad.go" <<'EOF'
package main
type Stringer interface{ String() string }
type Point struct{ X, Y int }
func (p *Point) String() string { return "point" }
func main() {
var byValue Stringer = Point{1, 2}
var byPointer Stringer = &Point{1, 2}
_, _ = byValue, byPointer
}
EOF
( cd "$tmp" && go vet ./bad.go 2>&1 | sed 's|^.*/bad.go|bad.go|' )
( cd "$tmp" && go build ./bad.go >/dev/null 2>&1 )
echo "--- go build exit code: $?"
echo
echo " Первая половина собралась и напечатала результат: Point реализует"
echo " Stringer, нигде об этом не заявляя. Вторая не собралась, и текст"
echo " ошибки называет причину сам — получатель у метода указательный,"
echo " поэтому метод не входит в набор методов ЗНАЧЕНИЯ. Строка с &Point"
echo " в том же файле законна: у указателя набор шире."