go - 使用 rand.Seed() 填充结构映射仅插入最后一个对象
问题描述
我有下面的代码,它的目的只是创建一个ComicBook
结构对象的映射并调用一个复制映射然后打印它的函数。当我在一切正常的情况下删除该rand.Seed()
行时SetId()
(除了 id 对每次运行都是恒定的,正如预期的那样),否则它只会将最后一个元素添加到地图中。为什么会这样?
comicBook.go
package src
import (
"math/rand"
"sync"
"time"
)
type ComicBook struct {
id int
name string
publisher string
sold bool
}
type Book interface {
GetId() int
SetId() int
GetName() string
GetPublisher() string
GetIsSold() bool
New(name string, author string) ComicBook
}
func (book ComicBook) SetId() int{
rand.Seed(time.Now().UTC().UnixNano())
id := rand.Intn(100)
book.id = id
return id
}
func (book ComicBook) New(name string, author string) ComicBook {
id := book.SetId()
b := ComicBook{id, name, author, false}
return b
}
func (book ComicBook) GetId() int{
return book.id
}
func (book ComicBook) GetName() string{
return book.name
}
func (book ComicBook) GetPublisher() string{
return book.publisher
}
func (book ComicBook) GetIsSold() bool{
return book.sold
}
main.go
package main
import (
"awesomeProject1/src"
"fmt"
)
var (
ComicBook src.ComicBook
)
func copyMap(m map[int]src.ComicBook) map[int]src.ComicBook {
newMap := make(map[int]src.ComicBook)
for k, v := range m {
newMap[k] = v
}
return newMap
}
func main() {
b := src.ComicBook{}.New("A", "B")
bTwo := src.ComicBook{}.New("The Dark Knight Returns", "DC Comics")
bThree := src.ComicBook{}.New("Watchmen", "DC Comics")
m := map[int]src.ComicBook{
b.GetId(): b,
bTwo.GetId(): bTwo,
bThree.GetId(): bThree,
}
newMap := copyMap(m)
for k, v := range newMap {
fmt.Println("Id: ", k, ", Name: ", v.GetName(), ", Publisher: ", v.GetPublisher(), ", Sold: ", v.GetIsSold())
}
}
输出:
Id: 91 , Name: Watchmen , Publisher: DC Comics , Sold: false
解决方案
您使用不安全的方法生成 id。我测试你的代码:
https://play.golang.org/p/S0_CWMqNH2-
rand.Seed(time.Now().UTC().UnixNano())
fmt.Println(time.Now().UTC().UnixNano())
id := rand.Intn(100)
fmt.Println(id)
这个不保存。您可以认为,相同的键可以是 1/100 BUT。您没有读到这些操作之间的时间可能太短,因此密钥本身与我的测试相同:
1257894000000000000
0
1257894000000000000
0
1257894000000000000
0
使用单个变量来保存种子,如下所示:(我使用全局变量,但您可以在 ComicBook 结构中添加种子变量)
import (
"math/rand"
"fmt"
)
var seed int
...
func (book *ComicBook) SetId() int{
seed += 1
rand.Seed(int64(seed))
id := rand.Intn(100)
并测试:
1
81
2
86
3
8
在您的代码中,任何地图元素都有 0 键并相互重写,但现在:
map[8:{8 false} 81:{81 false} 86:{86 false}]
map[8:{8 false} 81:{81 false} 86:{86 false}]
Id: 86 , Name: , Publisher: , Sold: false
Id: 8 , Name: , Publisher: , Sold: false
Id: 81 , Name: , Publisher: , Sold: false
https://play.golang.org/p/Z9_tFNdlBqp
并且,如果对 id 使用变量,则无需使用 rand:
func (book *ComicBook) SetId() int{
seed += 1
book.id = seed
fmt.Println(book.id)
return seed
}
推荐阅读
- hive - 数据摄取问题 hive:java.lang.OutOfMemoryError:无法创建新的本机线程
- azure-storage - ACS AEM Commons - acs-aem-commons-bundle 找不到类
- android - Android - 除了值之外,如何从 JSON 中获取键名
- java - Android Studio 中的白色 AdView
- json - 从 SQL Server 2016 中的 json 数据返回值
- qlikview - Qlikview -- 在表达式中使用带有变量的 If
- javascript - 计算立方体之间的距离(当存在环绕时)
- javafx - 打印对话框后 JavaFX 应用程序变得不可用
- kubernetes - 让我们用 Helm 在 Traefik 上加密
- google-cloud-functions - Google Cloud Functions 是否支持使用 Python 3.7 运行时进行代码编译?