How to rewrite rand.Seed(1) when migrate from go 1.13 to 1.20.1?

huangapple go评论89阅读模式
英文:

How to rewrite rand.Seed(1) when migrate from go 1.13 to 1.20.1?

问题

文件 bench.go

package bench

import "os"

func FileLen(f string, bufsize int) (int, error) {
	file, err := os.Open(f)
	if err != nil {
		return 0, err
	}
	defer file.Close()
	count := 0
	buf := make([]byte, bufsize)
	for {
		num, err := file.Read(buf)
		count += num
		if err != nil {
			break
		}
	}
	return count, nil
}

文件 bench_test.go

package bench

import (
	"fmt"
	"math/rand"
	"os"
	"testing"
)

func TestMain(m *testing.M) {
	makeData()
	exitVal := m.Run()
	os.Remove("testdata/data.txt")
	os.Exit(exitVal)
}

// makeData makes our data file for us. Rather than checking in a large file, we recreate it for the test.
// By setting the random seed to the same value every time, we ensure that we generate the same file every time.
// This random seed generates a file that's 65,204 bytes long.
func makeData() {
	file, err := os.Create("testdata/data.txt")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	rand.Seed(1)
	for i := 0; i < 10000; i++ {
		data := makeWord(rand.Intn(10) + 1)
		file.Write(data)
	}
}

func makeWord(l int) []byte {
	out := make([]byte, l+1)
	for i := 0; i < l; i++ {
		out[i] = 'a' + byte(rand.Intn(26))
	}
	out[l] = '\n'
	return out
}

func TestFileLen(t *testing.T) {
	result, err := FileLen("testdata/data.txt", 1)
	if err != nil {
		t.Fatal(err)
	}
	if result != 65204 {
		t.Error("Expected 65204, got", result)
	}
}

var blackhole int

func BenchmarkFileLen1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		result, err := FileLen("testdata/data.txt", 1)
		if err != nil {
			b.Fatal(err)
		}
		blackhole = result
	}
}

func BenchmarkFileLen(b *testing.B) {
	for _, v := range []int{1, 10, 100, 1000, 10000, 100000} {
		b.Run(fmt.Sprintf("FileLen-%d", v), func(b *testing.B) {
			for i := 0; i < b.N; i++ {
				result, err := FileLen("testdata/data.txt", v)
				if err != nil {
					b.Fatal(err)
				}
				blackhole = result
			}
		})
	}
}

How to rewrite rand.Seed(1) when migrate from go 1.13 to 1.20.1?

https://github.com/learning-go-book-2evy/test_examples/blob/master/bench/bench_test.go#L27

我尝试将 rand.Seed(1) 更改为 rand.NewSource(1),但测试失败了。在从 Go 1.13 迁移到 1.20.1 时如何重写 rand.Seed(1)

英文:

File bench.go

package bench

import &quot;os&quot;

func FileLen(f string, bufsize int) (int, error) {
	file, err := os.Open(f)
	if err != nil {
		return 0, err
	}
	defer file.Close()
	count := 0
	buf := make([]byte, bufsize)
	for {
		num, err := file.Read(buf)
		count += num
		if err != nil {
			break
		}
	}
	return count, nil
}

File bench_test.go

package bench

import (
	&quot;fmt&quot;
	&quot;math/rand&quot;
	&quot;os&quot;
	&quot;testing&quot;
)

func TestMain(m *testing.M) {
	makeData()
	exitVal := m.Run()
	os.Remove(&quot;testdata/data.txt&quot;)
	os.Exit(exitVal)
}

// makeData makes our data file for us. Rather than checking in a large file, we recreate it for the test.
// By setting the random seed to the same value every time, we ensure that we generate the same file every time.
// This random seed generates a file that&#39;s 65,204 bytes long.
func makeData() {
	file, err := os.Create(&quot;testdata/data.txt&quot;)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	rand.Seed(1)
	for i := 0; i &lt; 10000; i++ {
		data := makeWord(rand.Intn(10) + 1)
		file.Write(data)
	}
}

func makeWord(l int) []byte {
	out := make([]byte, l+1)
	for i := 0; i &lt; l; i++ {
		out[i] = &#39;a&#39; + byte(rand.Intn(26))
	}
	out[l] = &#39;\n&#39;
	return out
}

func TestFileLen(t *testing.T) {
	result, err := FileLen(&quot;testdata/data.txt&quot;, 1)
	if err != nil {
		t.Fatal(err)
	}
	if result != 65204 {
		t.Error(&quot;Expected 65204, got&quot;, result)
	}
}

var blackhole int

func BenchmarkFileLen1(b *testing.B) {
	for i := 0; i &lt; b.N; i++ {
		result, err := FileLen(&quot;testdata/data.txt&quot;, 1)
		if err != nil {
			b.Fatal(err)
		}
		blackhole = result
	}
}

func BenchmarkFileLen(b *testing.B) {
	for _, v := range []int{1, 10, 100, 1000, 10000, 100000} {
		b.Run(fmt.Sprintf(&quot;FileLen-%d&quot;, v), func(b *testing.B) {
			for i := 0; i &lt; b.N; i++ {
				result, err := FileLen(&quot;testdata/data.txt&quot;, v)
				if err != nil {
					b.Fatal(err)
				}
				blackhole = result
			}
		})
	}
}

How to rewrite rand.Seed(1) when migrate from go 1.13 to 1.20.1?

https://github.com/learning-go-book-2evy/test_examples/blob/master/bench/bench_test.go#L27

I tried change to rand.NewSource(1) but test fail. How to rewrite rand.Seed(1) when migrate from go 1.13 to 1.20.1?

答案1

得分: 3

截至Go 1.20.1,rand.Rand文档中存在一个错误。它写道:

> 需要特定结果序列的程序应使用NewRand(NewSource(seed))。

PRNG的构造函数应该是New,而不是NewRand

要替换全局种子的使用,将rand.NewSource的返回值传递给rand.New以获取一个PRNG。然后,该PRNG具有与包级函数相同的API:

package main

import "math/rand"

func main() {
    rng := rand.New(rand.NewSource(1))
    n := rng.Intn(10) + 1 // 替换rand.Intn
    _ = n
}

将原始代码更改为以下内容将通过基准测试:

func makeData() {
    file, err := os.Create("testdata/data.txt")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    r := rand.New(rand.NewSource(1))
    for i := 0; i < 10000; i++ {
        data := makeWord(r.Intn(10)+1, r)
        file.Write(data)
    }
}

func makeWord(l int, r *rand.Rand) []byte {
    out := make([]byte, l+1)
    for i := 0; i < l; i++ {
        out[i] = 'a' + byte(r.Intn(26))
    }
    out[l] = '\n'
    return out
}
英文:

As of Go 1.20.1 there is an error in the documentation for rand.Rand. It reads

> Programs that need a specific result sequence should use NewRand(NewSource(seed)).

The constructor for the PRNG is called New, not NewRand.

To replace uses of the global seed, pass the return value of rand.NewSource to rand.New to obtain a PRNG. This PRNG then has the same API as the package level functions:

package main

import &quot;math/rand&quot;

func main() {
	rng := rand.New(rand.NewSource(1))
	n := rng.Intn(10) + 1 // instead of rand.Intn
	_ = n
}

Changing the original to the following will pass the benchmark tests:

func makeData() {
	file, err := os.Create(&quot;testdata/data.txt&quot;)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	r := rand.New(rand.NewSource(1))
	for i := 0; i &lt; 10000; i++ {
		data := makeWord(r.Intn(10)+1, r)
		file.Write(data)
	}
}

func makeWord(l int, r *rand.Rand) []byte {
	out := make([]byte, l+1)
	for i := 0; i &lt; l; i++ {
		out[i] = &#39;a&#39; + byte(r.Intn(26))
	}
	out[l] = &#39;\n&#39;
	return out
}

huangapple
  • 本文由 发表于 2023年3月6日 15:29:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75648129.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定