[Hier](http://qiita.com/hiroykam/items/2fea445fd2d489354c34#%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AC%E3%83%BC%E3 Als ich Generatoren in PHP und Python3 mit% 82% BF untersuchte, untersuchte ich, wie dies in Golang und Ruby realisiert werden kann.
Ich habe numbers.txt
gelesen und einen einfachen Generator vorbereitet, der die folgenden Ausgabeergebnisse liefert.
numbers.txt
zero
one
two
three
four
five
Ausgabeergebnis
0:zero
1:one
2:two
3:three
4:four
5:five
Verifiziert mit PHP 5.6. Ich habe PHP7 nicht ausgewählt, weil ich diesmal nicht "Yield from" verwendet habe.
<?php
function my_generator($name)
{
$file = fopen($name, "r");
if ($file) {
while ($line = fgets($file)) {
yield $line;
}
}
fclose($file);
}
$g = my_generator("numbers.txt");
foreach ($g as $k => $v) {
print($k. ":". $v);
}
Dies kann auf die gleiche Weise wie bei PHP erreicht werden. Ich habe 3.5 als Python-Version verwendet.
def my_generator(name):
with open(name) as lines:
for line in lines:
yield line
g = my_generator("numbers.txt")
for k, v in enumerate(g):
print("%s:%s" % (k, v), end="")
Golang hat hier nicht das Äquivalent von PHP oder Python Yield
(siehe Referenz hier). Daher haben wir mit dem Goroutine-Kanal oder -Verschluss etwas Ähnliches erreicht.
Unter der Annahme, dass die Anzahl der Zeilen in numbers.txt
sehr groß sein wird, gibt es Bedenken hinsichtlich der Leistung.
package main
import (
"bufio"
"fmt"
"os"
)
func yield(fp *os.File) chan string {
ch := make(chan string)
go func() {
defer close(ch)
scanner := bufio.NewScanner(fp)
for scanner.Scan() {
ch <- scanner.Text()
}
if err := scanner.Err(); err != nil {
panic(err)
}
} ()
return ch
}
func main() {
fp, err := os.Open("numbers.txt")
if err != nil {
panic(err)
}
defer fp.Close()
i := 0
for s := range(yield(fp)) {
fmt.Printf("%d:%s\n", i, s)
i++
}
}
Möglicherweise gibt es eine Möglichkeit, mit sync.Mutex
zu synchronisieren.
package main
import (
"bufio"
"fmt"
"os"
)
func yield(fp *os.File) func() (bool, string) {
scanner := bufio.NewScanner(fp)
return func() (bool, string) {
t := scanner.Scan()
if err := scanner.Err(); err != nil {
panic(err)
}
return t, scanner.Text()
}
}
func main() {
fp, err := os.Open("numbers.txt")
if err != nil {
panic(err)
}
defer fp.Close()
y := yield(fp)
for i := 0;;i++ {
t, s := y()
if !t { break }
fmt.Printf("%d:%s\n", i, s)
}
}
Ruby hat auch "Yield", aber es ist eine Funktionsdefinition, die Blöcke anstelle eines Generators wie PHP / Python empfängt. Die Funktion, die dem Generator von PHP / Python entspricht, enthält einen Enumerator, der wie folgt beschrieben wird.
def my_generator(name)
return to_enum(__method__, name) unless block_given?
IO.foreach(name) do |line|
yield(line.chomp)
end
end
g = my_generator('numbers.txt')
g.with_index { |l, i| p '%d:%s' % [i, l] }
Wenn hier ein Block vorhanden ist, wird der Block verarbeitet, und wenn kein Block vorhanden ist, kann er als eine Methode behandelt werden, die Enumerator zurückgibt.
Recommended Posts