Comments 7
Первый же пример выводит (как и ожидалось): one two three -> https://goplay.tools/snippet/NZZL2FlYFh4
В 1.21 выводит, как у автора, а в 1.22 — как по «здравому смыслу»: поправили. Про это писали недавно
Previously, the variables declared by a “for” loop were created once and updated by each iteration. In Go 1.22, each iteration of the loop creates new variables, to avoid accidental sharing bugs. The transition support tooling described in the proposal continues to work in the same way it did in Go 1.21.
P.s. На сайтах где можно запускать Go код версии 1.21 почему-то код не всегда запускает. Поэтому я либо запускал код локально, либо на сайте https://www.programiz.com/golang/online-compiler/ (они судя по всему еще не обновили версию)
Для локального запуска 1.21
docker-compose.yaml
version: "3.7"
services:
app:
container_name: vprint_example-1.21
build:
dockerfile: Dockerfile
context: .
volumes:
- ./main.go:/app
Dockerfile
FROM golang:1.21.10-alpine3.20 as builder
LABEL maintainer = "Some maintainer"
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
RKDIR /root/
COPY --from=builder /app/main .
EXPOSE 10000 10000
CMD ["./main"]
main.go
package main
import (
"fmt"
"time"
)
type field struct {
name string
}
func (p *field) print() {
fmt.Printf("Запустился v.print(%p)\n", p)
fmt.Println(p.name)
}
func main() {
data := []field{{"one"}, {"two"}, {"three"}}
for i, v := range data {
go func() {
v.print()
}()
fmt.Printf("Отработала итерация %d\n", i)
}
time.Sleep(3 * time.Second)
// горутины выводят: three, three, three
}
Когда-нибудь гоферы научатся писать циклы без ошибок с горутинами и без лишних аллокаций, но видимо в другом мире
он всегда мне казался каким-то недоделанным языком, с этим ужасным синтаксисом, с вечными if err != nil
оказывается я был прав
Интересный пример кода на Go и зашоренность мышления