Хоча я схвалюю ваше занепокоєння з приводу відсутності цієї мовної функції, ви, мабуть, просто захочете використовувати звичайний for
цикл. І вам, мабуть, буде з цим все гаразд, ніж ви думаєте, коли пишете більше Go-коду.
Я написав цей пакет iter - який підтримується простим, ідіоматичним for
циклом, який повертає значення за a chan int
- у спробі покращити дизайн, знайдений у https://github.com/bradfitz/iter , на який було зазначено, проблеми кешування та продуктивності, а також розумна, але дивна та неінтуїтивна реалізація. Моя власна версія працює так само:
package main
import (
"fmt"
"github.com/drgrib/iter"
)
func main() {
for i := range iter.N(10) {
fmt.Println(i)
}
}
Однак бенчмаркінг виявив, що використання каналу було дуже дорогим варіантом. Порівняння трьох методів, за допомогою яких можна запустити iter_test.go
в моєму пакеті
go test -bench=. -run=.
кількісно визначає, наскільки низькі його показники
BenchmarkForMany-4 5000 329956 ns/op 0 B/op 0 allocs/op
BenchmarkDrgribIterMany-4 5 229904527 ns/op 195 B/op 1 allocs/op
BenchmarkBradfitzIterMany-4 5000 337952 ns/op 0 B/op 0 allocs/op
BenchmarkFor10-4 500000000 3.27 ns/op 0 B/op 0 allocs/op
BenchmarkDrgribIter10-4 500000 2907 ns/op 96 B/op 1 allocs/op
BenchmarkBradfitzIter10-4 100000000 12.1 ns/op 0 B/op 0 allocs/op
У цьому процесі цей показник також показує, як bradfitz
рішення має низькі результати порівняно з вбудованим for
пунктом для розміру циклу 10
.
Коротше кажучи, видається, що поки що не знайдено способу дублювання продуктивності вбудованого for
пункту, надаючи простий синтаксис на [0,n)
зразок того, що знайдений у Python та Ruby.
Що шкода, тому що, мабуть, команді Go було б легко додати до компілятора просте правило, щоб змінити рядок типу
for i := range 10 {
fmt.Println(i)
}
до того ж машинного коду, що і for i := 0; i < 10; i++
.
Однак, щоб бути справедливим, після написання свого власного iter.N
(але перед порівняльним оцінкою) я повернувся через нещодавно написану програму, щоб побачити всі місця, де я міг би її використати. Насправді їх було не так багато. У нежиттєвому розділі мого коду було лише одне місце, куди я міг обійтись без більш повного за замовчуванням for
.
Тож, хоча це може здатися, це величезне розчарування для мови в принципі, ви можете виявити - як і я, - що ви насправді цього не потребуєте на практиці. Як відомо, що Роб Пайк говорить про дженерики, ви, можливо, насправді не пропустите цю функцію настільки, наскільки думаєте, що хочете.