O intervalo do Go pode iterar em mapas e fatias, mas eu queria saber se existe uma maneira de iterar em um intervalo de números, algo como isto:
for i := range [1..10] {
fmt.Println(i)
}
Ou existe uma maneira de representar o intervalo de números inteiros no Go, como o Ruby faz com a classe Range ?
Aqui está um programa para comparar as duas maneiras sugeridas até agora
Compile assim para gerar desmontagem
Aqui está simples (removi as instruções não da lista)
configuração
ciclo
E aqui está with_iter
configuração
ciclo
Assim, você pode ver que a solução iter é consideravelmente mais cara, mesmo estando totalmente alinhada na fase de configuração. Na fase do loop, há uma instrução extra no loop, mas não é tão ruim.
Eu usaria o simples para loop.
fonte
runtime.makeslice
e a outra não - eu não preciso de um benchmark para saber que será muito mais lento!runtime.makeslice
é inteligente o suficiente para não alocar memória se você solicitar uma alocação de tamanho zero. No entanto, o que foi dito acima ainda o chama e, de acordo com o seu benchmark, leva 10nS mais na minha máquina.Foi sugerido por Mark Mishyn usar a fatia, mas não há razão para criar uma matriz com
make
e usar nafor
fatia retornada quando a matriz criada via literal pode ser usada e é mais curtafonte
for range [5]int{} {
5
aqui é um literal e não pode ser determinado em tempo de execução.O iter é um pacote muito pequeno que apenas fornece uma maneira diferente de fazer iterações sobre números inteiros.
Rob Pike (um autor de Go) criticou :
fonte
iter
versão realmente usa menos digitação, porquerange
eiter
vão autocomplete.for
loops não são um cidadão de primeira classe do Unix como eles estão. Além disso, ao contráriofor
, osseq
fluxos para saída padrão de uma sequência de números. Se iterar ou não sobre eles depende do consumidor. Emborafor i in $(seq 1 10); do ... done
seja comum no Shell, é apenas uma maneira de fazer um loop for, que é apenas uma maneira de consumir a saídaseq
, embora muito comum.i in range(10)
exatamente da mesma maneirai := 0; i < 10; i++
.Aqui está uma referência para comparar uma
for
instrução Go com uma instrução ForClause e Gorange
usando oiter
pacote.iter_test.go
Resultado:
fonte
Embora eu tenha pena da sua preocupação por não ter esse recurso de idioma, você provavelmente só desejará usar um
for
loop normal . E você provavelmente ficará mais bem com isso do que pensa ao escrever mais código Go.Eu escrevi este pacote iter - que é apoiado por um
for
loop idiomático simples que retorna valores acima de umchan int
- em uma tentativa de melhorar o design encontrado em https://github.com/bradfitz/iter , que foi apontado como tendo problemas de cache e desempenho, bem como uma implementação inteligente, mas estranha e não intuitiva. Minha própria versão funciona da mesma maneira:No entanto, o benchmarking revelou que o uso de um canal era uma opção muito cara. A comparação dos 3 métodos, que podem ser executados
iter_test.go
no meu pacote usandoquantifica o quão ruim é seu desempenho
No processo, essa referência também mostra como a
bradfitz
solução tem um desempenho inferior ao dafor
cláusula interna para um tamanho de loop de10
.Em suma, até agora não parece haver nenhuma maneira de duplicar o desempenho do
for
cláusula interna, fornecendo uma sintaxe simples,[0,n)
como a encontrada em Python e Ruby.O que é uma pena, porque provavelmente seria fácil para a equipe Go adicionar uma regra simples ao compilador para alterar uma linha como
para o mesmo código de máquina que
for i := 0; i < 10; i++
.No entanto, para ser justo, depois de escrever o meu próprio
iter.N
(mas antes de compará-lo), voltei a um programa recentemente escrito para ver todos os lugares onde eu poderia usá-lo. Na verdade, não havia muitos. Havia apenas um ponto, em uma seção não vital do meu código, onde eu poderia sobreviver sem afor
cláusula padrão mais completa .Portanto, embora possa parecer uma decepção enorme para o idioma em princípio, você pode descobrir - como eu fiz - que realmente não precisa dele na prática. Como Rob Pike é conhecido por dizer sobre genéricos, você pode realmente não perder esse recurso tanto quanto pensa.
fonte
Se você deseja apenas iterar em um intervalo sem o uso de índices ou qualquer outra coisa, esse exemplo de código funcionou bem para mim. Nenhuma declaração extra necessária, não
_
. Não verifiquei o desempenho, no entanto.PS O primeiro dia em GoLang. Por favor, critique se for uma abordagem errada.
fonte
non-constant array bound
para mim.Você também pode conferir github.com/wushilin/stream
É um fluxo lento como o conceito de java.util.stream.
Espero que isto ajude
fonte
fonte
Eu escrevi um pacote no Golang que imita a função range do Python:
Pacote https://github.com/thedevsaddam/iter
fonte