github.com/wfusion/gofusion@v1.1.14/common/infra/drivers/orm/idgen/snowflake.go (about) 1 package idgen 2 3 import ( 4 "fmt" 5 "hash/fnv" 6 "log" 7 "net" 8 "os" 9 "reflect" 10 "sync" 11 "time" 12 13 "github.com/sony/sonyflake" 14 15 "github.com/wfusion/gofusion/common/utils" 16 ) 17 18 var ( 19 // NewSnowflakeType FIXME: should not be deleted to avoid compiler optimized 20 NewSnowflakeType = reflect.TypeOf(NewSnowflake) 21 22 snowflakeOnce sync.Once 23 snowflakeInstance *snowflake 24 ) 25 26 type snowflake struct { 27 instance *sonyflake.Sonyflake 28 } 29 30 // NewSnowflake it should be only one snowflake generator per service instance 31 func NewSnowflake() Generator { 32 snowflakeOnce.Do(func() { 33 flake := sonyflake.NewSonyflake(sonyflake.Settings{ 34 StartTime: time.Time{}, 35 // machine id: hash(host ip + local ip + pid)(8 bit) - local ip(8 bit) 36 MachineID: func() (id uint16, err error) { 37 pid := os.Getpid() 38 hostIP := utils.HostIPInDocker() 39 localIP := utils.ClientIP() 40 log.Printf("[Common] snowflake get machine id base [host[%s] local[%s] pid[%v]]", hostIP, localIP, pid) 41 if hostIP == "" { 42 hostIP = utils.ClientIP() 43 } 44 hash := fnv.New32a() 45 _, err = hash.Write([]byte(fmt.Sprintf("%s%s%v", hostIP, localIP, pid))) 46 if err != nil { 47 return 48 } 49 50 high := byte(hash.Sum32() % 255) 51 low := net.ParseIP(localIP).To4()[3] 52 id = uint16(high)<<8 | uint16(low) 53 log.Printf("[Common] snowflake get machine id [%X]", id) 54 return 55 }, 56 CheckMachineID: nil, 57 }) 58 if flake == nil { 59 panic(ErrNewGenerator) 60 } 61 snowflakeInstance = &snowflake{instance: flake} 62 }) 63 64 return snowflakeInstance 65 } 66 67 func (s *snowflake) Next(opts ...utils.OptionExtender) (id uint64, err error) { 68 return s.instance.NextID() 69 }