├── data-structures ├── matrix │ ├── README.md │ ├── matrix_test.go │ └── matrix.go ├── heap │ ├── util.go │ ├── heap_test.go │ └── heap.go ├── graph │ ├── undirected_graph.go │ ├── README.md │ ├── directed_graph.go │ ├── graph_test.go │ └── graph.go ├── stack │ ├── stack_test.go │ └── stack.go ├── queue │ ├── queue_test.go │ └── queue.go ├── binary-tree │ ├── bst_test.go │ └── bst.go ├── hash-tables │ ├── ht_test.go │ └── ht.go ├── list │ ├── list_test.go │ └── list.go ├── priority-queue │ ├── priority_queue.go │ └── priority_queue_test.go └── linked-list │ ├── linked_list_test.go │ └── linked_list.go ├── README.md ├── example ├── messages │ ├── build.bat │ ├── protos.proto │ └── protos.pb.go └── service │ └── server │ └── main.go ├── network ├── agent.go ├── conn.go ├── processor.go ├── tcp_conn.go ├── ws_conn.go ├── tcp_server.go ├── ws_client.go ├── tcp_client.go ├── tcp_msg.go └── ws_server.go ├── module └── module.go ├── util ├── semaphore.go ├── tools.go ├── stack.go ├── example_test.go ├── rand.go ├── map.go ├── conv.go ├── deepcopy.go ├── math.go ├── uuid.go └── uuid_test.go ├── service ├── service_test.go ├── serviceData.go └── service.go ├── proto └── proto.go ├── log ├── example_test.go ├── loggroup.go └── log.go ├── config └── serviceConfig.go ├── app └── app.go ├── gateframework ├── agent.go └── gate.go └── mysqldb ├── dbclient.go └── dbclient_test.go /data-structures/matrix/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ganet 2 | 游戏服务器框架,Actor,伸缩架构 3 | 4 | # 示例项目 5 | https://github.com/magicsea/h5game 6 | -------------------------------------------------------------------------------- /example/messages/build.bat: -------------------------------------------------------------------------------- 1 | protoc -I=. -I=%GOPATH%\src --gogoslick_out=plugins=grpc:. protos.proto 2 | -------------------------------------------------------------------------------- /network/agent.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | type Agent interface { 4 | Run() 5 | OnClose() 6 | } 7 | -------------------------------------------------------------------------------- /module/module.go: -------------------------------------------------------------------------------- 1 | package module 2 | 3 | type IModule interface { 4 | OnInit() bool 5 | OnDestroy() 6 | Run() 7 | } 8 | -------------------------------------------------------------------------------- /data-structures/heap/util.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | type Int int 4 | 5 | func (x Int) Less(than Item) bool { 6 | return x < than.(Int) 7 | } 8 | -------------------------------------------------------------------------------- /network/conn.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | type Conn interface { 8 | ReadMsg() ([]byte, error) 9 | WriteMsg(args ...[]byte) error 10 | LocalAddr() net.Addr 11 | RemoteAddr() net.Addr 12 | Close() 13 | Destroy() 14 | } 15 | -------------------------------------------------------------------------------- /util/semaphore.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | type Semaphore chan struct{} 4 | 5 | func MakeSemaphore(n int) Semaphore { 6 | return make(Semaphore, n) 7 | } 8 | 9 | func (s Semaphore) Acquire() { 10 | s <- struct{}{} 11 | } 12 | 13 | func (s Semaphore) Release() { 14 | <-s 15 | } 16 | -------------------------------------------------------------------------------- /data-structures/graph/undirected_graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | type UnGraph struct { 4 | graph 5 | } 6 | 7 | func NewUndirected() *UnGraph { 8 | return &UnGraph{ 9 | graph{ 10 | edgesCount: 0, 11 | edges: make(map[VertexId]map[VertexId]int), 12 | isDirected: false, 13 | }, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /network/processor.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | type Processor interface { 4 | // must goroutine safe 5 | Route(msg interface{}, userData interface{}) error 6 | // must goroutine safe 7 | Unmarshal(data []byte) (interface{}, error) 8 | // must goroutine safe 9 | Marshal(msg interface{}) ([][]byte, error) 10 | } 11 | -------------------------------------------------------------------------------- /data-structures/graph/README.md: -------------------------------------------------------------------------------- 1 | # graph-go [![Build Status](https://travis-ci.org/arnauddri/graph-go.svg?branch=master)](https://travis-ci.org/arnauddri/graph-go) [![Coverage Status](https://img.shields.io/coveralls/arnauddri/graph-go.svg)](https://coveralls.io/r/arnauddri/graph-go?branch=master) 2 | 3 | An implementation of several graph algorithms in Go 4 | -------------------------------------------------------------------------------- /util/tools.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "time" 4 | 5 | type TimeTaskFunc func() 6 | 7 | func StartLoopTask(t time.Duration, fun TimeTaskFunc) *time.Ticker { 8 | timeTicker := time.NewTicker(t) 9 | go func() { 10 | for { 11 | select { 12 | case <-timeTicker.C: 13 | fun() 14 | } 15 | } 16 | }() 17 | return timeTicker 18 | } 19 | -------------------------------------------------------------------------------- /service/service_test.go: -------------------------------------------------------------------------------- 1 | package service_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | 8 | . "github.com/magicsea/ganet/service" 9 | 10 | //"github.com/AsynkronIT/goconsole" 11 | "github.com/AsynkronIT/protoactor-go/actor" 12 | ) 13 | 14 | type hello struct { 15 | Who string 16 | } 17 | 18 | func Example(t *testing.T) { 19 | fmt.Println("service_test Example pass") 20 | props := actor.FromInstance(&BaseServer{}) 21 | pid := actor.Spawn(props) 22 | pid.Tell(&hello{Who: "Roger"}) 23 | time.Sleep(1) 24 | fmt.Println("service_test Example pass") 25 | pid.GracefulStop() 26 | } 27 | -------------------------------------------------------------------------------- /proto/proto.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/gogo/protobuf/proto" 7 | //"github.com/magicsea/ganet/config" 8 | ) 9 | 10 | //json pb 11 | var protoType string = "json" 12 | 13 | //json pb 默认json 14 | func SetProtoType(t string) { 15 | protoType = t 16 | } 17 | 18 | func Marshal(m proto.Message) ([]byte, error) { 19 | if protoType == "json" { 20 | return json.Marshal(m) 21 | } 22 | 23 | return proto.Marshal(m) 24 | } 25 | func Unmarshal(raw []byte, m proto.Message) error { 26 | if protoType == "json" { 27 | return json.Unmarshal(raw, m) 28 | } 29 | 30 | return proto.Unmarshal(raw, m) 31 | } 32 | -------------------------------------------------------------------------------- /data-structures/stack/stack_test.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | s := New() 10 | 11 | if !s.isEmpty() || 12 | s.len != 0 || 13 | s.Len() != 0 { 14 | t.Error() 15 | } 16 | 17 | s.Push(1) 18 | s.Push(2) 19 | s.Push(3) 20 | 21 | if s.stack[0] != 3 || 22 | s.stack[1] != 2 || 23 | s.stack[2] != 1 { 24 | fmt.Println(s.stack) 25 | t.Error() 26 | } 27 | 28 | if s.Len() != 3 { 29 | t.Error() 30 | } 31 | 32 | a := s.Pop() 33 | 34 | if a != 3 || s.Len() != 2 { 35 | t.Error() 36 | } 37 | 38 | b := s.Peek() 39 | 40 | if b != 2 { 41 | t.Error() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/messages/protos.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package messages; 3 | import "github.com/AsynkronIT/protoactor-go/actor/protos.proto"; 4 | 5 | message Connect { 6 | actor.PID Sender = 1; 7 | } 8 | 9 | message Connected { 10 | string Message = 1; 11 | } 12 | 13 | message SayRequest { 14 | string UserName = 1; 15 | string Message = 2; 16 | } 17 | 18 | message SayResponse { 19 | string UserName = 1; 20 | string Message = 2; 21 | } 22 | 23 | message NickRequest { 24 | string OldUserName = 1; 25 | string NewUserName = 2; 26 | } 27 | 28 | message NickResponse { 29 | string OldUserName = 1; 30 | string NewUserName = 2; 31 | } -------------------------------------------------------------------------------- /log/example_test.go: -------------------------------------------------------------------------------- 1 | package log_test 2 | 3 | import ( 4 | "github.com/magicsea/ganet/log" 5 | "testing" 6 | ) 7 | 8 | func TestLog(t *testing.T) { 9 | name := "Leaf" 10 | log.NewLogGroup("debug", "ss", true, 0) 11 | 12 | log.Debug("My name is %v", name) 13 | log.Info("My name is %v", name) 14 | log.Error("My name is %v", name) 15 | //log.Fatal("My name is %v", name) 16 | 17 | /* 18 | logger, err := log.New("release", "", l.LstdFlags) 19 | if err != nil { 20 | return 21 | } 22 | defer logger.Close() 23 | 24 | logger.Debug("will not print") 25 | logger.Info("My name is %v", name) 26 | */ 27 | //log.Export(logger) 28 | 29 | //log.Debug("will not print") 30 | //log.Info("My name is %v", name) 31 | } 32 | -------------------------------------------------------------------------------- /example/service/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/magicsea/ganet/example/messages" 5 | . "github.com/magicsea/ganet/service" 6 | "fmt" 7 | 8 | "github.com/AsynkronIT/goconsole" 9 | "github.com/AsynkronIT/protoactor-go/actor" 10 | ) 11 | 12 | type MyServer struct { 13 | BaseServer 14 | } 15 | 16 | func (s *MyServer) OnReceive(context actor.Context) { 17 | switch msg := context.Message().(type) { 18 | case *messages.SayRequest: 19 | fmt.Println("OnREC:", msg.UserName, msg.Message) 20 | } 21 | } 22 | func (s *MyServer) OnInit() { 23 | 24 | } 25 | func (s *MyServer) OnStart() { 26 | 27 | } 28 | 29 | func main() { 30 | s := &MyServer{} 31 | s.Init("127.0.0.1:8090", "server") 32 | console.ReadLine() 33 | } 34 | -------------------------------------------------------------------------------- /data-structures/queue/queue_test.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | q := New() 10 | 11 | if !q.isEmpty() || 12 | q.len != 0 || 13 | q.Len() != 0 { 14 | t.Error() 15 | } 16 | 17 | q.Push(1) 18 | q.Push(2) 19 | q.Push(3) 20 | 21 | if q.queue[0] != 1 || 22 | q.queue[1] != 2 || 23 | q.queue[2] != 3 { 24 | fmt.Println(q.queue) 25 | t.Error() 26 | } 27 | 28 | if q.Len() != 3 { 29 | t.Error() 30 | } 31 | 32 | a := q.Pop() 33 | 34 | if a != 1 || q.Len() != 2 { 35 | t.Error() 36 | } 37 | 38 | b := q.Peek() 39 | 40 | if b != 2 { 41 | t.Error() 42 | } 43 | 44 | q2 := New() 45 | q2.Push(0) 46 | q2.Push(1) 47 | q2.Push(2) 48 | q2.Push(3) 49 | 50 | f := func(o interface{}) bool { 51 | return o.(int) == 3 52 | } 53 | q2.PopRule(f) 54 | fmt.Println(q2.queue) 55 | } 56 | -------------------------------------------------------------------------------- /util/stack.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "runtime" 5 | 6 | "github.com/magicsea/ganet/log" 7 | "bytes" 8 | "fmt" 9 | //"github.com/davecgh/go-spew/spew" 10 | ) 11 | 12 | // 产生panic时的调用栈打印 13 | func PrintPanicStack(extras ...interface{}) { 14 | var buff bytes.Buffer 15 | var haveErr = false 16 | if x := recover(); x != nil { 17 | haveErr = true 18 | buff.WriteString(fmt.Sprintf("dump:%v\n", x)) 19 | //log.Error("dump:%v", x) 20 | i := 0 21 | funcName, file, line, ok := runtime.Caller(i) 22 | for ok { 23 | buff.WriteString(fmt.Sprintf("frame %v:[func:%v,file:%v,line:%v]\n", i, runtime.FuncForPC(funcName).Name(), file, line)) 24 | //log.Error("frame %v:[func:%v,file:%v,line:%v]\n", i, runtime.FuncForPC(funcName).Name(), file, line) 25 | i++ 26 | funcName, file, line, ok = runtime.Caller(i) 27 | } 28 | 29 | //for k := range extras { 30 | // buff.WriteString(fmt.Sprintf("EXRAS#%v DATA:%v\n", k, spew.Sdump(extras[k]))) 31 | //} 32 | } 33 | if haveErr { 34 | log.Error(buff.String()) 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /data-structures/binary-tree/bst_test.go: -------------------------------------------------------------------------------- 1 | package bst 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestTree(t *testing.T) { 9 | n := NewNode(1) 10 | m := NewNode(2) 11 | 12 | // Test compare 13 | if n.Compare(m) != -1 || m.Compare(n) != 1 || n.Compare(n) != 0 { 14 | fmt.Println(n.Compare(m)) 15 | t.Error() 16 | } 17 | 18 | tree := NewTree(n) 19 | 20 | tree.Insert(4) 21 | tree.Insert(2) 22 | tree.Insert(5) 23 | tree.Insert(3) 24 | tree.Insert(6) 25 | 26 | if tree.Size != 6 { 27 | fmt.Println(tree.Size) 28 | t.Error() 29 | } 30 | 31 | five := tree.Search(5) 32 | 33 | if five.Value != 5 || 34 | five.Parent.Value != 4 || 35 | five.Right.Value != 6 || 36 | five.Left != nil { 37 | fmt.Println(*tree.Search(5)) 38 | t.Error() 39 | } 40 | 41 | tree.Delete(5) 42 | 43 | if tree.Size != 5 { 44 | t.Error() 45 | } 46 | 47 | four := *tree.Search(4) 48 | if four.Right.Value != 6 || 49 | four.Left.Value != 2 || 50 | four.Parent.Value != 1 { 51 | fmt.Println(*tree.Search(4)) 52 | t.Error() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /data-structures/stack/stack.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "sync" 4 | 5 | type Stack struct { 6 | stack []interface{} 7 | len int 8 | lock sync.Mutex 9 | } 10 | 11 | func New() *Stack { 12 | s := &Stack{} 13 | s.stack = make([]interface{}, 0) 14 | s.len = 0 15 | 16 | return s 17 | } 18 | 19 | func (s *Stack) Len() int { 20 | s.lock.Lock() 21 | defer s.lock.Unlock() 22 | 23 | return s.len 24 | } 25 | 26 | func (s *Stack) isEmpty() bool { 27 | s.lock.Lock() 28 | defer s.lock.Unlock() 29 | 30 | return s.len == 0 31 | } 32 | 33 | func (s *Stack) Pop() (el interface{}) { 34 | s.lock.Lock() 35 | defer s.lock.Unlock() 36 | 37 | el, s.stack = s.stack[0], s.stack[1:] 38 | s.len-- 39 | return 40 | } 41 | 42 | func (s *Stack) Push(el interface{}) { 43 | s.lock.Lock() 44 | defer s.lock.Unlock() 45 | 46 | prepend := make([]interface{}, 1) 47 | prepend[0] = el 48 | s.stack = append(prepend, s.stack...) 49 | s.len++ 50 | } 51 | 52 | func (s *Stack) Peek() interface{} { 53 | s.lock.Lock() 54 | defer s.lock.Unlock() 55 | 56 | return s.stack[0] 57 | } 58 | -------------------------------------------------------------------------------- /service/serviceData.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "github.com/AsynkronIT/protoactor-go/actor" 5 | _ "github.com/AsynkronIT/protoactor-go/remote" 6 | ) 7 | 8 | type IServiceData interface { 9 | Init(addr string, name string, typename string) 10 | GetName() string 11 | GetType() string 12 | GetAddress() string 13 | SetPID(pid *actor.PID) 14 | GetPID() *actor.PID 15 | } 16 | 17 | type ServiceData struct { 18 | Address string 19 | Name string 20 | TypeName string 21 | Pid *actor.PID 22 | } 23 | 24 | func (s *ServiceData) Init(addr string, name string, typename string) { 25 | s.Address = addr 26 | s.Name = name 27 | s.TypeName = typename 28 | } 29 | func (s *ServiceData) OnRun() { 30 | 31 | } 32 | func (s *ServiceData) GetType() string { 33 | return s.TypeName 34 | } 35 | func (s *ServiceData) GetName() string { 36 | return s.Name 37 | } 38 | func (s *ServiceData) GetAddress() string { 39 | return s.Address 40 | } 41 | func (s *ServiceData) SetPID(pid *actor.PID) { 42 | s.Pid = pid 43 | } 44 | func (s *ServiceData) GetPID() *actor.PID { 45 | return s.Pid 46 | } 47 | func (s *ServiceData) OnDestory() { 48 | 49 | } 50 | -------------------------------------------------------------------------------- /data-structures/hash-tables/ht_test.go: -------------------------------------------------------------------------------- 1 | package ht 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestHt(t *testing.T) { 9 | ht := New(1000) 10 | ht.Put("foo", "bar") 11 | ht.Put("fiz", "buzz") 12 | ht.Put("bruce", "wayne") 13 | ht.Put("peter", "parker") 14 | ht.Put("clark", "kent") 15 | 16 | // Test simple get 17 | val, err := ht.Get("foo") 18 | if err != nil || val != "bar" || ht.Size != 5 { 19 | fmt.Println(val, err) 20 | t.Error() 21 | } 22 | 23 | ht.Put("peter", "bob") 24 | // Test "peter" has been updated 25 | val, err = ht.Get("peter") 26 | if err != nil && val == "bob" || ht.Size != 5 { 27 | fmt.Println(val, err) 28 | t.Error() 29 | } 30 | 31 | // Test delete 32 | ht.Del("peter") 33 | val, err = ht.Get("peter") 34 | if val != "" || err == nil || ht.Size != 4 { 35 | t.Error() 36 | } 37 | 38 | counter := 0 39 | f := func(a *item) { 40 | counter++ 41 | } 42 | 43 | ht.ForEach(f) 44 | 45 | if counter != 4 { 46 | t.Error() 47 | } 48 | } 49 | 50 | func TestHash(t *testing.T) { 51 | test := "Hello World!" 52 | 53 | if hashCode(test) != 969099747 { 54 | fmt.Println(hashCode(test)) 55 | t.Error() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /data-structures/heap/heap_test.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMinHeap(t *testing.T) { 9 | h := NewMin() 10 | 11 | h.Insert(Int(8)) 12 | h.Insert(Int(7)) 13 | h.Insert(Int(6)) 14 | h.Insert(Int(3)) 15 | h.Insert(Int(1)) 16 | h.Insert(Int(0)) 17 | h.Insert(Int(2)) 18 | h.Insert(Int(4)) 19 | h.Insert(Int(9)) 20 | h.Insert(Int(5)) 21 | 22 | sorted := make([]Int, 0) 23 | for h.Len() > 0 { 24 | sorted = append(sorted, h.Extract().(Int)) 25 | } 26 | 27 | for i := 0; i < len(sorted)-2; i++ { 28 | if sorted[i] > sorted[i+1] { 29 | fmt.Println(sorted) 30 | t.Error() 31 | } 32 | } 33 | } 34 | 35 | func TestMaxHeap(t *testing.T) { 36 | h := NewMax() 37 | 38 | h.Insert(Int(8)) 39 | h.Insert(Int(7)) 40 | h.Insert(Int(6)) 41 | h.Insert(Int(3)) 42 | h.Insert(Int(1)) 43 | h.Insert(Int(0)) 44 | h.Insert(Int(2)) 45 | h.Insert(Int(4)) 46 | h.Insert(Int(9)) 47 | h.Insert(Int(5)) 48 | 49 | sorted := make([]Int, 0) 50 | for h.Len() > 0 { 51 | sorted = append(sorted, h.Extract().(Int)) 52 | } 53 | 54 | for i := 0; i < len(sorted)-2; i++ { 55 | if sorted[i] < sorted[i+1] { 56 | fmt.Println(sorted) 57 | t.Error() 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /data-structures/list/list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestList(t *testing.T) { 9 | l := New(1, 2, 3, 4, 5) 10 | l.Add(6) 11 | l.Append(7, 8) 12 | l2 := New(9, 10) 13 | l.Concat(l2) 14 | fmt.Println(l) 15 | fmt.Println(l.Find(func(o interface{}) bool { 16 | return o.(int) == 7 17 | })) 18 | l.Add(7) 19 | fmt.Println(l.FindAll(func(o interface{}) bool { 20 | return o.(int) == 7 21 | })) 22 | fmt.Println(l.RemoveRule(func(o interface{}) bool { 23 | return o.(int) == 7 24 | })) 25 | fmt.Println(l) 26 | l.Insert(5, 99) 27 | fmt.Println(l) 28 | 29 | fmt.Println("remove:", l.Remove(5), l) 30 | fmt.Println(l.RemoveRule(func(o interface{}) bool { 31 | return o.(int) == 7 32 | })) 33 | fmt.Println("rule:", l) 34 | l.Insert(0, 99) 35 | l.Insert(5, 99) 36 | l.Insert(5, 99) 37 | l.Insert(999, 99) 38 | fmt.Println(l) 39 | fmt.Println(l.RemoveAllRule(func(o interface{}) bool { 40 | return o.(int) == 99 41 | })) 42 | fmt.Println("ruleall:", l) 43 | l.Each(func(o interface{}) { 44 | fmt.Println(o.(int) * 2) 45 | }) 46 | fmt.Println(l) 47 | l3 := New(88, 88, 99, 99) 48 | l.DeepCopy(l3) 49 | fmt.Println("dc", l) 50 | l.Clear() 51 | fmt.Println(l) 52 | } 53 | -------------------------------------------------------------------------------- /data-structures/priority-queue/priority_queue.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "github.com/magicsea/ganet/data-structures/heap" 5 | "github.com/magicsea/ganet/data-structures/queue" 6 | ) 7 | 8 | type Item struct { 9 | Value interface{} 10 | Priority int 11 | } 12 | 13 | func NewItem(value interface{}, priority int) (i *Item) { 14 | return &Item{ 15 | Value: value, 16 | Priority: priority, 17 | } 18 | } 19 | 20 | func (x Item) Less(than heap.Item) bool { 21 | return x.Priority < than.(Item).Priority 22 | } 23 | 24 | type PQ struct { 25 | data heap.Heap 26 | } 27 | 28 | func NewMax() (q *PQ) { 29 | return &PQ{ 30 | data: *heap.NewMax(), 31 | } 32 | } 33 | 34 | func NewMin() (q *PQ) { 35 | return &PQ{ 36 | data: *heap.NewMin(), 37 | } 38 | } 39 | 40 | func (pq *PQ) Len() int { 41 | return pq.data.Len() 42 | } 43 | 44 | func (pq *PQ) Insert(el Item) { 45 | pq.data.Insert(heap.Item(el)) 46 | } 47 | 48 | func (pq *PQ) Extract() (el Item) { 49 | return pq.data.Extract().(Item) 50 | } 51 | 52 | func (pq *PQ) ChangePriority(val interface{}, priority int) { 53 | var storage = queue.New() 54 | 55 | popped := pq.Extract() 56 | 57 | for val != popped.Value { 58 | if pq.Len() == 0 { 59 | panic("Item not found") 60 | } 61 | 62 | storage.Push(popped) 63 | popped = pq.Extract() 64 | } 65 | 66 | popped.Priority = priority 67 | pq.data.Insert(popped) 68 | 69 | for storage.Len() > 0 { 70 | pq.data.Insert(storage.Shift().(heap.Item)) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /data-structures/queue/queue.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import "sync" 4 | 5 | type Queue struct { 6 | queue []interface{} 7 | len int 8 | lock *sync.Mutex 9 | } 10 | 11 | func New() *Queue { 12 | queue := &Queue{} 13 | queue.queue = make([]interface{}, 0) 14 | queue.len = 0 15 | queue.lock = new(sync.Mutex) 16 | 17 | return queue 18 | } 19 | 20 | func (q *Queue) Len() int { 21 | //q.lock.Lock() 22 | //defer q.lock.Unlock() 23 | 24 | return q.len 25 | } 26 | 27 | func (q *Queue) isEmpty() bool { 28 | q.lock.Lock() 29 | defer q.lock.Unlock() 30 | 31 | return q.len == 0 32 | } 33 | 34 | func (q *Queue) Pop() (el interface{}) { 35 | //q.lock.Lock() 36 | //defer q.lock.Unlock() 37 | 38 | el, q.queue = q.queue[0], q.queue[1:] 39 | q.len-- 40 | return 41 | } 42 | 43 | type RuleFunc func(interface{}) bool 44 | 45 | func (q *Queue) PopRule(rule RuleFunc) (el interface{}) { 46 | //q.lock.Lock() 47 | //defer q.lock.Unlock() 48 | for index := 0; index < q.len; index++ { 49 | if rule(q.queue[index]) { 50 | el = q.queue[index] 51 | q.queue = append(q.queue[:index], q.queue[index+1:]...) 52 | q.len-- 53 | break 54 | } 55 | } 56 | 57 | return 58 | } 59 | 60 | func (q *Queue) Push(el interface{}) { 61 | //q.lock.Lock() 62 | //defer q.lock.Unlock() 63 | 64 | q.queue = append(q.queue, el) 65 | q.len++ 66 | 67 | return 68 | } 69 | 70 | func (q *Queue) Peek() interface{} { 71 | q.lock.Lock() 72 | defer q.lock.Unlock() 73 | 74 | return q.queue[0] 75 | } 76 | -------------------------------------------------------------------------------- /util/example_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | "github.com/magicsea/ganet/util" 5 | "fmt" 6 | ) 7 | 8 | func ExampleMap() { 9 | m := new(util.Map) 10 | 11 | fmt.Println(m.Get("key")) 12 | m.Set("key", "value") 13 | fmt.Println(m.Get("key")) 14 | m.Del("key") 15 | fmt.Println(m.Get("key")) 16 | 17 | m.Set(1, "1") 18 | m.Set(2, 2) 19 | m.Set("3", 3) 20 | 21 | fmt.Println(m.Len()) 22 | 23 | // Output: 24 | // 25 | // value 26 | // 27 | // 3 28 | } 29 | 30 | func ExampleRandGroup() { 31 | i := util.RandGroup(0, 0, 50, 50) 32 | switch i { 33 | case 2, 3: 34 | fmt.Println("ok") 35 | } 36 | 37 | // Output: 38 | // ok 39 | } 40 | 41 | func ExampleRandInterval() { 42 | v := util.RandInterval(-1, 1) 43 | switch v { 44 | case -1, 0, 1: 45 | fmt.Println("ok") 46 | } 47 | 48 | // Output: 49 | // ok 50 | } 51 | 52 | func ExampleRandIntervalN() { 53 | r := util.RandIntervalN(-1, 0, 2) 54 | if r[0] == -1 && r[1] == 0 || 55 | r[0] == 0 && r[1] == -1 { 56 | fmt.Println("ok") 57 | } 58 | 59 | // Output: 60 | // ok 61 | } 62 | 63 | func ExampleDeepCopy() { 64 | src := []int{1, 2, 3} 65 | 66 | var dst []int 67 | util.DeepCopy(&dst, &src) 68 | 69 | for _, v := range dst { 70 | fmt.Println(v) 71 | } 72 | 73 | // Output: 74 | // 1 75 | // 2 76 | // 3 77 | } 78 | 79 | func ExampleDeepClone() { 80 | src := []int{1, 2, 3} 81 | 82 | dst := util.DeepClone(src).([]int) 83 | 84 | for _, v := range dst { 85 | fmt.Println(v) 86 | } 87 | 88 | // Output: 89 | // 1 90 | // 2 91 | // 3 92 | } 93 | -------------------------------------------------------------------------------- /data-structures/graph/directed_graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | type DirGraph struct { 4 | graph 5 | } 6 | 7 | func NewDirected() *DirGraph { 8 | return &DirGraph{ 9 | graph{ 10 | edgesCount: 0, 11 | edges: make(map[VertexId]map[VertexId]int), 12 | isDirected: true, 13 | }, 14 | } 15 | } 16 | 17 | func (g *graph) GetPredecessors(vertex VertexId) VerticesIterable { 18 | iterator := func() <-chan VertexId { 19 | ch := make(chan VertexId) 20 | go func() { 21 | if connected, ok := g.edges[vertex]; ok { 22 | for VertexId, _ := range connected { 23 | if g.IsEdge(VertexId, vertex) { 24 | ch <- VertexId 25 | } 26 | } 27 | } 28 | close(ch) 29 | }() 30 | return ch 31 | } 32 | 33 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 34 | } 35 | 36 | func (g *graph) GetSuccessors(vertex VertexId) VerticesIterable { 37 | iterator := func() <-chan VertexId { 38 | ch := make(chan VertexId) 39 | go func() { 40 | if connected, ok := g.edges[vertex]; ok { 41 | for VertexId, _ := range connected { 42 | if g.IsEdge(vertex, VertexId) { 43 | ch <- VertexId 44 | } 45 | } 46 | } 47 | close(ch) 48 | }() 49 | return ch 50 | } 51 | 52 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 53 | } 54 | 55 | func (g *DirGraph) Reverse() *DirGraph { 56 | r := NewDirected() 57 | 58 | vertices := g.VerticesIter() 59 | for vertex := range vertices { 60 | r.AddVertex(vertex) 61 | } 62 | 63 | edges := g.EdgesIter() 64 | for edge := range edges { 65 | r.AddEdge(edge.To, edge.From, 1) 66 | } 67 | 68 | return r 69 | } 70 | -------------------------------------------------------------------------------- /util/rand.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | func init() { 9 | rand.Seed(time.Now().UnixNano()) 10 | } 11 | 12 | func RandGroup(p ...uint32) int { 13 | if p == nil { 14 | panic("args not found") 15 | } 16 | 17 | r := make([]uint32, len(p)) 18 | for i := 0; i < len(p); i++ { 19 | if i == 0 { 20 | r[0] = p[0] 21 | } else { 22 | r[i] = r[i-1] + p[i] 23 | } 24 | } 25 | 26 | rl := r[len(r)-1] 27 | if rl == 0 { 28 | return 0 29 | } 30 | 31 | rn := uint32(rand.Int63n(int64(rl))) 32 | for i := 0; i < len(r); i++ { 33 | if rn < r[i] { 34 | return i 35 | } 36 | } 37 | 38 | panic("bug") 39 | } 40 | 41 | func RandInterval(b1, b2 int32) int32 { 42 | if b1 == b2 { 43 | return b1 44 | } 45 | 46 | min, max := int64(b1), int64(b2) 47 | if min > max { 48 | min, max = max, min 49 | } 50 | return int32(rand.Int63n(max-min+1) + min) 51 | } 52 | 53 | func RandIntervalN(b1, b2 int32, n uint32) []int32 { 54 | if b1 == b2 { 55 | return []int32{b1} 56 | } 57 | 58 | min, max := int64(b1), int64(b2) 59 | if min > max { 60 | min, max = max, min 61 | } 62 | l := max - min + 1 63 | if int64(n) > l { 64 | n = uint32(l) 65 | } 66 | 67 | r := make([]int32, n) 68 | m := make(map[int32]int32) 69 | for i := uint32(0); i < n; i++ { 70 | v := int32(rand.Int63n(l) + min) 71 | 72 | if mv, ok := m[v]; ok { 73 | r[i] = mv 74 | } else { 75 | r[i] = v 76 | } 77 | 78 | lv := int32(l - 1 + min) 79 | if v != lv { 80 | if mv, ok := m[lv]; ok { 81 | m[v] = mv 82 | } else { 83 | m[v] = lv 84 | } 85 | } 86 | 87 | l-- 88 | } 89 | 90 | return r 91 | } 92 | -------------------------------------------------------------------------------- /data-structures/priority-queue/priority_queue_test.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMaxPriorityQueue(t *testing.T) { 9 | h := NewMax() 10 | 11 | h.Insert(*NewItem(8, 10)) 12 | h.Insert(*NewItem(7, 11)) 13 | h.Insert(*NewItem(6, 12)) 14 | h.Insert(*NewItem(3, 13)) 15 | h.Insert(*NewItem(1, 14)) 16 | h.Insert(*NewItem(0, 15)) 17 | h.Insert(*NewItem(2, 16)) 18 | h.Insert(*NewItem(4, 17)) 19 | h.Insert(*NewItem(9, 18)) 20 | h.Insert(*NewItem(5, 19)) 21 | 22 | sorted := make([]Item, 0) 23 | for h.Len() > 0 { 24 | sorted = append(sorted, h.Extract()) 25 | } 26 | 27 | for i := 0; i < len(sorted)-2; i++ { 28 | if sorted[i].Priority < sorted[i+1].Priority { 29 | fmt.Println(sorted) 30 | t.Error() 31 | } 32 | } 33 | } 34 | 35 | func TestMinPriorityQueue(t *testing.T) { 36 | h := NewMin() 37 | 38 | h.Insert(*NewItem(8, 10)) 39 | h.Insert(*NewItem(7, 11)) 40 | h.Insert(*NewItem(6, 12)) 41 | h.Insert(*NewItem(3, 13)) 42 | h.Insert(*NewItem(1, 14)) 43 | h.Insert(*NewItem(0, 15)) 44 | h.Insert(*NewItem(2, 16)) 45 | h.Insert(*NewItem(4, 17)) 46 | h.Insert(*NewItem(9, 18)) 47 | h.Insert(*NewItem(5, 19)) 48 | 49 | sorted := make([]Item, 0) 50 | for h.Len() > 0 { 51 | sorted = append(sorted, h.Extract()) 52 | } 53 | 54 | for i := 0; i < len(sorted)-2; i++ { 55 | if sorted[i].Priority > sorted[i+1].Priority { 56 | fmt.Println(sorted) 57 | t.Error() 58 | } 59 | } 60 | } 61 | 62 | func TestChangePriority(t *testing.T) { 63 | h := NewMax() 64 | 65 | h.Insert(*NewItem(8, 10)) 66 | h.Insert(*NewItem(7, 11)) 67 | h.Insert(*NewItem(6, 12)) 68 | h.Insert(*NewItem(3, 13)) 69 | h.Insert(*NewItem(1, 14)) 70 | h.Insert(*NewItem(0, 15)) 71 | h.Insert(*NewItem(2, 16)) 72 | h.Insert(*NewItem(4, 17)) 73 | h.Insert(*NewItem(9, 18)) 74 | h.Insert(*NewItem(5, 19)) 75 | 76 | h.ChangePriority(8, 66) 77 | popped := h.Extract() 78 | 79 | if popped.Value != 8 { 80 | t.Error() 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /config/serviceConfig.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | type ServiceNodeConfig struct { 4 | ServiceName string `json:"serviceName"` //服务名 (gameserver) 5 | ServiceType string `json:"serviceType"` //服务类型 (gameserver1) 6 | RemoteAddr string `json:"remoteAddr"` //远程地址 (127.0.0.1:80 or "",空字符表示本地启动) 7 | Conf map[string]interface{} `json:"conf"` //单体配置 8 | } 9 | type LogConfig struct { 10 | LogLevel string `json:"level"` 11 | LogPath string `json:"path"` 12 | LogFlag int `json:"flag"` 13 | } 14 | 15 | type ServiceConfig struct { 16 | Services []*ServiceNodeConfig `json:"local"` 17 | RemoteAddrs map[string]string `json:"remote"` 18 | LogConf *LogConfig `json:"log"` 19 | Proto string `json:"proto"` 20 | } 21 | 22 | var globleConfig ServiceConfig 23 | 24 | func SetGlobleConfig(conf *ServiceConfig) { 25 | globleConfig = *conf 26 | } 27 | 28 | func GetGlobleConfig() *ServiceConfig { 29 | return &globleConfig 30 | } 31 | 32 | func GetService(ser string) *ServiceNodeConfig { 33 | for _,v := range globleConfig.Services { 34 | if v.ServiceName==ser { 35 | return v 36 | } 37 | } 38 | return nil 39 | } 40 | 41 | func GetServiceConfig(ser string, key string) interface{} { 42 | node := GetService(ser) 43 | return node.Conf[key] 44 | } 45 | 46 | func GetServiceConfigString(ser string, key string) string { 47 | if v:=GetServiceConfig(ser,key);v!=nil { 48 | return v.(string) 49 | } 50 | return "" 51 | } 52 | 53 | func GetServiceConfigInt(ser string, key string) int { 54 | f := GetServiceConfig(ser, key).(float64) 55 | return int(f) 56 | } 57 | 58 | //GetServiceAddress 获取服务地址,先去remote找,没有就到本地找 59 | func GetServiceAddress(serviceName string) string { 60 | if globleConfig.RemoteAddrs != nil { 61 | return globleConfig.RemoteAddrs[serviceName] 62 | } else { 63 | return GetService(serviceName).RemoteAddr 64 | } 65 | } 66 | 67 | func IsJsonProto() bool { 68 | return globleConfig.Proto=="json" 69 | } 70 | -------------------------------------------------------------------------------- /util/map.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type Map struct { 8 | sync.RWMutex 9 | m map[interface{}]interface{} 10 | } 11 | 12 | func (m *Map) init() { 13 | if m.m == nil { 14 | m.m = make(map[interface{}]interface{}) 15 | } 16 | } 17 | 18 | func (m *Map) UnsafeGet(key interface{}) interface{} { 19 | if m.m == nil { 20 | return nil 21 | } else { 22 | return m.m[key] 23 | } 24 | } 25 | 26 | func (m *Map) Get(key interface{}) interface{} { 27 | m.RLock() 28 | defer m.RUnlock() 29 | return m.UnsafeGet(key) 30 | } 31 | 32 | func (m *Map) UnsafeSet(key interface{}, value interface{}) { 33 | m.init() 34 | m.m[key] = value 35 | } 36 | 37 | func (m *Map) Set(key interface{}, value interface{}) { 38 | m.Lock() 39 | defer m.Unlock() 40 | m.UnsafeSet(key, value) 41 | } 42 | 43 | func (m *Map) TestAndSet(key interface{}, value interface{}) interface{} { 44 | m.Lock() 45 | defer m.Unlock() 46 | 47 | m.init() 48 | 49 | if v, ok := m.m[key]; ok { 50 | return v 51 | } else { 52 | m.m[key] = value 53 | return nil 54 | } 55 | } 56 | 57 | func (m *Map) UnsafeDel(key interface{}) { 58 | m.init() 59 | delete(m.m, key) 60 | } 61 | 62 | func (m *Map) Del(key interface{}) { 63 | m.Lock() 64 | defer m.Unlock() 65 | m.UnsafeDel(key) 66 | } 67 | 68 | func (m *Map) UnsafeLen() int { 69 | if m.m == nil { 70 | return 0 71 | } else { 72 | return len(m.m) 73 | } 74 | } 75 | 76 | func (m *Map) Len() int { 77 | m.RLock() 78 | defer m.RUnlock() 79 | return m.UnsafeLen() 80 | } 81 | 82 | func (m *Map) UnsafeRange(f func(interface{}, interface{})) { 83 | if m.m == nil { 84 | return 85 | } 86 | for k, v := range m.m { 87 | f(k, v) 88 | } 89 | } 90 | 91 | func (m *Map) RLockRange(f func(interface{}, interface{})) { 92 | m.RLock() 93 | defer m.RUnlock() 94 | m.UnsafeRange(f) 95 | } 96 | 97 | func (m *Map) LockRange(f func(interface{}, interface{})) { 98 | m.Lock() 99 | defer m.Unlock() 100 | m.UnsafeRange(f) 101 | } 102 | -------------------------------------------------------------------------------- /log/loggroup.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import "log" 4 | 5 | type LogGroup struct { 6 | loggers []*Logger 7 | } 8 | 9 | var gGroup *LogGroup 10 | 11 | //var gLogger *Logger 12 | 13 | func init() { 14 | gLogger, _ := New("debug", "", "", log.LstdFlags|log.Lshortfile) 15 | gGroup = new(LogGroup) 16 | gGroup.loggers = append(gGroup.loggers, gLogger) 17 | } 18 | func NewLogGroup(strLevel string, pathname string, isStdout bool, flag int) error { 19 | 20 | if pathname != "" { 21 | debug, err := New("debug", "debug_", pathname, flag) 22 | if err != nil { 23 | return err 24 | } 25 | info, err := New("info", "info_", pathname, flag) 26 | if err != nil { 27 | return err 28 | } 29 | erro, err := New("error", "error_", pathname, flag) 30 | if err != nil { 31 | return err 32 | } 33 | fatal, err := New("fatal", "fatal_", pathname, flag) 34 | if err != nil { 35 | return err 36 | } 37 | gGroup = &LogGroup{[]*Logger{debug, info, erro, fatal}} 38 | } else { 39 | gGroup = &LogGroup{} 40 | } 41 | 42 | if isStdout { 43 | gLogger, _ := New(strLevel, "", "", log.LstdFlags|log.Lshortfile) 44 | gGroup.loggers = append(gGroup.loggers, gLogger) 45 | } 46 | return nil 47 | } 48 | 49 | func Debug(format string, a ...interface{}) { 50 | for _, v := range gGroup.loggers { 51 | v.Debug(format, a...) 52 | } 53 | } 54 | 55 | func Info(format string, a ...interface{}) { 56 | for _, v := range gGroup.loggers { 57 | v.Info(format, a...) 58 | } 59 | } 60 | 61 | func _println(format string, a ...interface{}) { 62 | //str := fmt.Sprint(a) 63 | for _, v := range gGroup.loggers { 64 | v.Println(format, a...) 65 | } 66 | 67 | } 68 | 69 | func Error(format string, a ...interface{}) { 70 | //fmt.Println("Error ", len(gGroup.loggers), gGroup.loggers) 71 | for _, v := range gGroup.loggers { 72 | v.Error(format, a...) 73 | } 74 | } 75 | 76 | func Fatal(format string, a ...interface{}) { 77 | for _, v := range gGroup.loggers { 78 | v.Fatal(format, a...) 79 | } 80 | } 81 | 82 | func Close() { 83 | for _, v := range gGroup.loggers { 84 | v.Close() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /util/conv.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "reflect" 7 | "strconv" 8 | ) 9 | 10 | // ToStr interface to string 11 | func SetValueFromStr(value reflect.Value, s string) error { 12 | switch value.Interface().(type) { 13 | case bool: 14 | val, err := strconv.ParseBool(s) 15 | if err != nil { 16 | return err 17 | } 18 | value.SetBool(val) 19 | case float32: 20 | val, err := strconv.ParseFloat(s, 32) 21 | if err != nil { 22 | return err 23 | } 24 | value.SetFloat(val) 25 | case float64: 26 | val, err := strconv.ParseFloat(s, 64) 27 | if err != nil { 28 | return err 29 | } 30 | value.SetFloat(val) 31 | case int, int32: 32 | val, err := strconv.ParseInt(s, 10, 32) 33 | if err != nil { 34 | return err 35 | } 36 | value.SetInt(val) 37 | case int8: 38 | val, err := strconv.ParseInt(s, 10, 8) 39 | if err != nil { 40 | return err 41 | } 42 | value.SetInt(val) 43 | case int16: 44 | val, err := strconv.ParseInt(s, 10, 16) 45 | if err != nil { 46 | return err 47 | } 48 | value.SetInt(val) 49 | case int64: 50 | val, err := strconv.ParseInt(s, 10, 64) 51 | if err != nil { 52 | return err 53 | } 54 | value.SetInt(val) 55 | case uint, uint32: 56 | val, err := strconv.ParseUint(s, 10, 32) 57 | if err != nil { 58 | return err 59 | } 60 | value.SetUint(val) 61 | case uint8: 62 | val, err := strconv.ParseUint(s, 10, 8) 63 | if err != nil { 64 | return err 65 | } 66 | value.SetUint(val) 67 | case uint16: 68 | val, err := strconv.ParseUint(s, 10, 16) 69 | if err != nil { 70 | return err 71 | } 72 | value.SetUint(val) 73 | case uint64: 74 | val, err := strconv.ParseUint(s, 10, 16) 75 | if err != nil { 76 | return err 77 | } 78 | value.SetUint(val) 79 | case string: 80 | value.SetString(s) 81 | case []byte: 82 | value.SetBytes([]byte(s)) 83 | case []int32: 84 | var val []int32 85 | var err = json.Unmarshal([]byte(s), &val) 86 | if err != nil { 87 | return err 88 | } 89 | value.Set(reflect.ValueOf(val)) 90 | default: 91 | return fmt.Errorf("unkown-type :%v", reflect.TypeOf(value)) 92 | } 93 | return nil 94 | } 95 | -------------------------------------------------------------------------------- /data-structures/heap/heap.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type Item interface { 8 | Less(than Item) bool 9 | } 10 | 11 | type Heap struct { 12 | sync.Mutex 13 | data []Item 14 | min bool 15 | } 16 | 17 | func New() *Heap { 18 | return &Heap{ 19 | data: make([]Item, 0), 20 | } 21 | } 22 | 23 | func NewMin() *Heap { 24 | return &Heap{ 25 | data: make([]Item, 0), 26 | min: true, 27 | } 28 | } 29 | 30 | func NewMax() *Heap { 31 | return &Heap{ 32 | data: make([]Item, 0), 33 | min: false, 34 | } 35 | } 36 | 37 | func (h *Heap) isEmpty() bool { 38 | return len(h.data) == 0 39 | } 40 | 41 | func (h *Heap) Len() int { 42 | return len(h.data) 43 | } 44 | 45 | func (h *Heap) Get(n int) Item { 46 | return h.data[n] 47 | } 48 | 49 | func (h *Heap) Insert(n Item) { 50 | h.Lock() 51 | defer h.Unlock() 52 | 53 | h.data = append(h.data, n) 54 | h.siftUp() 55 | 56 | return 57 | } 58 | 59 | func (h *Heap) Extract() (el Item) { 60 | h.Lock() 61 | defer h.Unlock() 62 | if h.Len() == 0 { 63 | return 64 | } 65 | 66 | el = h.data[0] 67 | last := h.data[h.Len()-1] 68 | if h.Len() == 1 { 69 | h.data = nil 70 | return 71 | } 72 | 73 | h.data = append([]Item{last}, h.data[1:h.Len()-1]...) 74 | h.siftDown() 75 | 76 | return 77 | } 78 | 79 | func (h *Heap) siftUp() { 80 | for i, parent := h.Len()-1, h.Len()-1; i > 0; i = parent { 81 | parent = i >> 1 82 | if h.Less(h.Get(i), h.Get(parent)) { 83 | h.data[parent], h.data[i] = h.data[i], h.data[parent] 84 | } else { 85 | break 86 | } 87 | } 88 | } 89 | 90 | func (h *Heap) siftDown() { 91 | for i, child := 0, 1; i < h.Len() && i<<1+1 < h.Len(); i = child { 92 | child = i<<1 + 1 93 | 94 | if child+1 <= h.Len()-1 && h.Less(h.Get(child+1), h.Get(child)) { 95 | child++ 96 | } 97 | 98 | if h.Less(h.Get(i), h.Get(child)) { 99 | break 100 | } 101 | 102 | h.data[i], h.data[child] = h.data[child], h.data[i] 103 | } 104 | } 105 | 106 | func (h *Heap) Less(a, b Item) bool { 107 | if h.min { 108 | return a.Less(b) 109 | } else { 110 | return b.Less(a) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /data-structures/matrix/matrix_test.go: -------------------------------------------------------------------------------- 1 | package matrix 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMakeMatrix(t *testing.T) { 8 | a := []float64{1, 2, 3, 4, 5, 6} 9 | A := MakeMatrix(a, 3, 2) 10 | 11 | if A.cols != 2 || 12 | A.rows != 3 || 13 | !FloatArrayEquals(A.Elements, a) { 14 | t.Error() 15 | } 16 | } 17 | 18 | func TestCount(t *testing.T) { 19 | a := []float64{1, 2, 3, 4, 5, 6} 20 | A := MakeMatrix(a, 3, 2) 21 | 22 | if A.CountRows() != 3 { 23 | t.Error() 24 | } 25 | if A.CountCols() != 2 { 26 | t.Error() 27 | } 28 | } 29 | 30 | func TestGetElm(t *testing.T) { 31 | a := []float64{1, 2, 3, 4, 5, 6} 32 | A := MakeMatrix(a, 3, 2) 33 | 34 | for i := 0; i < 3; i++ { 35 | if A.GetElm(0, i) != float64(i+1) { 36 | t.Error() 37 | } 38 | } 39 | } 40 | 41 | func TestSetElm(t *testing.T) { 42 | a := []float64{1, 2, 3, 4, 5, 6} 43 | A := MakeMatrix(a, 3, 2) 44 | 45 | A.SetElm(0, 0, 10) 46 | 47 | if A.GetElm(0, 0) != 10 { 48 | t.Error() 49 | } 50 | } 51 | 52 | func TestTrace(t *testing.T) { 53 | a := []float64{1, 2, 3, 4} 54 | A := MakeMatrix(a, 2, 2) 55 | 56 | if A.trace() != 5 { 57 | t.Error() 58 | } 59 | } 60 | 61 | func TestAdd(t *testing.T) { 62 | a := []float64{1, 1, 1, 1} 63 | A := MakeMatrix(a, 2, 2) 64 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 65 | 66 | A.add(A) 67 | if !FloatArrayEquals(A.Elements, B.Elements) { 68 | t.Error() 69 | } 70 | } 71 | 72 | func TestSubstract(t *testing.T) { 73 | a := []float64{1, 1, 1, 1} 74 | A := MakeMatrix(a, 2, 2) 75 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 76 | 77 | B.substract(A) 78 | if !FloatArrayEquals(A.Elements, B.Elements) { 79 | t.Error() 80 | } 81 | } 82 | 83 | func TestScale(t *testing.T) { 84 | a := []float64{1, 1, 1, 1} 85 | A := MakeMatrix(a, 2, 2) 86 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 87 | 88 | A.scale(2) 89 | 90 | if !FloatArrayEquals(A.Elements, B.Elements) { 91 | t.Error() 92 | } 93 | } 94 | 95 | func FloatArrayEquals(a []float64, b []float64) bool { 96 | if len(a) != len(b) { 97 | return false 98 | } 99 | for i, v := range a { 100 | if v != b[i] { 101 | return false 102 | } 103 | } 104 | return true 105 | } 106 | -------------------------------------------------------------------------------- /util/deepcopy.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | // reference: https://github.com/mohae/deepcopy 4 | import ( 5 | "reflect" 6 | ) 7 | 8 | func deepCopy(dst, src reflect.Value) { 9 | switch src.Kind() { 10 | case reflect.Interface: 11 | value := src.Elem() 12 | if !value.IsValid() { 13 | return 14 | } 15 | newValue := reflect.New(value.Type()).Elem() 16 | deepCopy(newValue, value) 17 | dst.Set(newValue) 18 | case reflect.Ptr: 19 | value := src.Elem() 20 | if !value.IsValid() { 21 | return 22 | } 23 | dst.Set(reflect.New(value.Type())) 24 | deepCopy(dst.Elem(), value) 25 | case reflect.Map: 26 | dst.Set(reflect.MakeMap(src.Type())) 27 | keys := src.MapKeys() 28 | for _, key := range keys { 29 | value := src.MapIndex(key) 30 | newValue := reflect.New(value.Type()).Elem() 31 | deepCopy(newValue, value) 32 | dst.SetMapIndex(key, newValue) 33 | } 34 | case reflect.Slice: 35 | dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap())) 36 | for i := 0; i < src.Len(); i++ { 37 | deepCopy(dst.Index(i), src.Index(i)) 38 | } 39 | case reflect.Struct: 40 | typeSrc := src.Type() 41 | for i := 0; i < src.NumField(); i++ { 42 | value := src.Field(i) 43 | tag := typeSrc.Field(i).Tag 44 | if value.CanSet() && tag.Get("deepcopy") != "-" { 45 | deepCopy(dst.Field(i), value) 46 | } 47 | } 48 | default: 49 | dst.Set(src) 50 | } 51 | } 52 | 53 | func DeepCopy(dst, src interface{}) { 54 | typeDst := reflect.TypeOf(dst) 55 | typeSrc := reflect.TypeOf(src) 56 | if typeDst != typeSrc { 57 | panic("DeepCopy: " + typeDst.String() + " != " + typeSrc.String()) 58 | } 59 | if typeSrc.Kind() != reflect.Ptr { 60 | panic("DeepCopy: pass arguments by address") 61 | } 62 | 63 | valueDst := reflect.ValueOf(dst).Elem() 64 | valueSrc := reflect.ValueOf(src).Elem() 65 | if !valueDst.IsValid() || !valueSrc.IsValid() { 66 | panic("DeepCopy: invalid arguments") 67 | } 68 | 69 | deepCopy(valueDst, valueSrc) 70 | } 71 | 72 | func DeepClone(v interface{}) interface{} { 73 | dst := reflect.New(reflect.TypeOf(v)).Elem() 74 | deepCopy(dst, reflect.ValueOf(v)) 75 | return dst.Interface() 76 | } 77 | 78 | //是否扩展类型 79 | func IsStructType(k reflect.Kind) bool { 80 | if k >= reflect.Array && k != reflect.String { 81 | return true 82 | } 83 | return false 84 | } 85 | -------------------------------------------------------------------------------- /data-structures/linked-list/linked_list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestLinkedList(t *testing.T) { 9 | // Test Prepend/Get 10 | l := NewList() 11 | 12 | l.Prepend(NewNode(1)) 13 | l.Prepend(NewNode(2)) 14 | l.Prepend(NewNode(3)) 15 | 16 | zero := *slice(l.Get(0))[0].(*Node).Value.(*Node) 17 | one := *slice(l.Get(1))[0].(*Node).Value.(*Node) 18 | two := *slice(l.Get(2))[0].(*Node).Value.(*Node) 19 | 20 | if zero != *NewNode(3) || 21 | one != *NewNode(2) || 22 | two != *NewNode(1) { 23 | 24 | fmt.Println(*one.Value.(*Node), *NewNode(2)) 25 | fmt.Println(zero.Value) 26 | fmt.Println(one.Value) 27 | fmt.Println(two.Value) 28 | t.Error() 29 | } 30 | 31 | // Test Append 32 | k := NewList() 33 | 34 | k.Append(NewNode(1)) 35 | k.Append(NewNode(2)) 36 | k.Append(NewNode(3)) 37 | 38 | zero = *slice(k.Get(0))[0].(*Node).Value.(*Node) 39 | one = *slice(k.Get(1))[0].(*Node).Value.(*Node) 40 | two = *slice(k.Get(2))[0].(*Node).Value.(*Node) 41 | 42 | if zero != *NewNode(1) || 43 | one != *NewNode(2) || 44 | two != *NewNode(3) { 45 | 46 | fmt.Println(zero.Value) 47 | fmt.Println(one.Value) 48 | fmt.Println(two.Value) 49 | t.Error() 50 | } 51 | 52 | // Test Add 53 | k.Add(NewNode(8), 1) 54 | 55 | zero = *slice(k.Get(0))[0].(*Node).Value.(*Node) 56 | one = *slice(k.Get(1))[0].(*Node).Value.(*Node) 57 | two = *slice(k.Get(2))[0].(*Node).Value.(*Node) 58 | 59 | if zero != *NewNode(1) || 60 | one != *NewNode(8) || 61 | two != *NewNode(2) { 62 | 63 | fmt.Println(zero.Value) 64 | fmt.Println(one.Value) 65 | fmt.Println(two.Value) 66 | 67 | t.Error() 68 | } 69 | 70 | // Test Concat 71 | l.Concat(k) 72 | if l.Len() != 7 { 73 | t.Error() 74 | } 75 | 76 | // Test Each 77 | counter := 0 78 | f := func(node *Node) { 79 | counter += node.Value.(int) 80 | } 81 | 82 | l.Map(f) 83 | if counter != 20 { 84 | t.Error() 85 | } 86 | 87 | // Test Find 88 | index, _ := l.Find(NewNode(1)) 89 | if index != 3 { 90 | fmt.Println(index) 91 | t.Error() 92 | } 93 | 94 | // Test Remove 95 | l.Remove(*NewNode(8)) 96 | 97 | counter = 0 98 | l.Map(func(n *Node) { 99 | counter += n.Value.(int) 100 | }) 101 | 102 | if counter != 12 { 103 | t.Error() 104 | } 105 | 106 | // Test Clear 107 | l.Clear() 108 | if l.Len() != 0 { 109 | t.Error() 110 | } 111 | 112 | } 113 | 114 | func slice(args ...interface{}) []interface{} { 115 | return args 116 | } 117 | -------------------------------------------------------------------------------- /network/tcp_conn.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "net" 5 | "sync" 6 | 7 | "github.com/magicsea/ganet/log" 8 | ) 9 | 10 | type ConnSet map[net.Conn]struct{} 11 | 12 | type TCPConn struct { 13 | sync.Mutex 14 | conn net.Conn 15 | writeChan chan []byte 16 | closeFlag bool 17 | msgParser *MsgParser 18 | } 19 | 20 | func newTCPConn(conn net.Conn, pendingWriteNum int, msgParser *MsgParser) *TCPConn { 21 | tcpConn := new(TCPConn) 22 | tcpConn.conn = conn 23 | tcpConn.writeChan = make(chan []byte, pendingWriteNum) 24 | tcpConn.msgParser = msgParser 25 | 26 | go func() { 27 | for b := range tcpConn.writeChan { 28 | if b == nil { 29 | break 30 | } 31 | 32 | _, err := conn.Write(b) 33 | if err != nil { 34 | break 35 | } 36 | } 37 | 38 | conn.Close() 39 | tcpConn.Lock() 40 | tcpConn.closeFlag = true 41 | tcpConn.Unlock() 42 | }() 43 | 44 | return tcpConn 45 | } 46 | 47 | func (tcpConn *TCPConn) doDestroy() { 48 | tcpConn.conn.(*net.TCPConn).SetLinger(0) 49 | tcpConn.conn.Close() 50 | 51 | if !tcpConn.closeFlag { 52 | close(tcpConn.writeChan) 53 | tcpConn.closeFlag = true 54 | } 55 | } 56 | 57 | func (tcpConn *TCPConn) Destroy() { 58 | tcpConn.Lock() 59 | defer tcpConn.Unlock() 60 | 61 | tcpConn.doDestroy() 62 | } 63 | 64 | func (tcpConn *TCPConn) Close() { 65 | tcpConn.Lock() 66 | defer tcpConn.Unlock() 67 | if tcpConn.closeFlag { 68 | return 69 | } 70 | 71 | tcpConn.doWrite(nil) 72 | tcpConn.closeFlag = true 73 | } 74 | 75 | func (tcpConn *TCPConn) doWrite(b []byte) { 76 | if len(tcpConn.writeChan) == cap(tcpConn.writeChan) { 77 | log.Debug("close conn: channel full") 78 | tcpConn.doDestroy() 79 | return 80 | } 81 | 82 | tcpConn.writeChan <- b 83 | } 84 | 85 | // b must not be modified by the others goroutines 86 | func (tcpConn *TCPConn) Write(b []byte) { 87 | tcpConn.Lock() 88 | defer tcpConn.Unlock() 89 | if tcpConn.closeFlag || b == nil { 90 | return 91 | } 92 | 93 | tcpConn.doWrite(b) 94 | } 95 | 96 | func (tcpConn *TCPConn) Read(b []byte) (int, error) { 97 | return tcpConn.conn.Read(b) 98 | } 99 | 100 | func (tcpConn *TCPConn) LocalAddr() net.Addr { 101 | return tcpConn.conn.LocalAddr() 102 | } 103 | 104 | func (tcpConn *TCPConn) RemoteAddr() net.Addr { 105 | return tcpConn.conn.RemoteAddr() 106 | } 107 | 108 | func (tcpConn *TCPConn) ReadMsg() ([]byte, error) { 109 | return tcpConn.msgParser.Read(tcpConn) 110 | } 111 | 112 | func (tcpConn *TCPConn) WriteMsg(args ...[]byte) error { 113 | return tcpConn.msgParser.Write(tcpConn, args...) 114 | } 115 | -------------------------------------------------------------------------------- /app/app.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | . "github.com/magicsea/ganet/config" 5 | "github.com/magicsea/ganet/log" 6 | "github.com/magicsea/ganet/module" 7 | "github.com/magicsea/ganet/service" 8 | "github.com/magicsea/ganet/util" 9 | "os" 10 | "os/signal" 11 | ) 12 | 13 | type MakeServiceFunc func() service.IService 14 | 15 | var ( 16 | serviceTypeMap map[string]MakeServiceFunc 17 | services []service.IService 18 | modules []module.IModule 19 | ) 20 | 21 | func init() { 22 | serviceTypeMap = make(map[string]MakeServiceFunc) 23 | } 24 | 25 | func RegisterService(serviceType string, f MakeServiceFunc) { 26 | serviceTypeMap[serviceType] = f 27 | } 28 | 29 | func Run(conf *ServiceConfig, ms ...module.IModule) { 30 | SetGlobleConfig(conf) 31 | 32 | //init log 33 | if conf.LogConf.LogLevel != "" { 34 | err := log.NewLogGroup(conf.LogConf.LogLevel, conf.LogConf.LogPath, true, conf.LogConf.LogFlag) 35 | if err != nil { 36 | panic(err) 37 | } 38 | //log.Export(logger) 39 | defer log.Close() 40 | } 41 | 42 | defer util.PrintPanicStack() 43 | 44 | log.Info("log started.") 45 | modules = ms 46 | for _, m := range modules { 47 | if !m.OnInit() { 48 | log.Fatal("%v module.OnInit fail", m) 49 | } 50 | } 51 | for _, m := range modules { 52 | m.Run() 53 | } 54 | //cluster.InitCluster() 55 | //生成服务对象 56 | for _, sc := range conf.Services { 57 | makefunc := serviceTypeMap[sc.ServiceType] 58 | if makefunc != nil { 59 | ser := makefunc() 60 | log.Info("生成服务:%s", sc.ServiceName) 61 | ser.Init(sc.RemoteAddr, sc.ServiceName, sc.ServiceType) 62 | services = append(services, ser) 63 | } else { 64 | log.Fatal("未注册的服务类型:%v", sc) 65 | } 66 | } 67 | 68 | //init 69 | for _, ser := range services { 70 | log.Info("init服务:%s", ser.GetName()) 71 | ser.OnInit() 72 | } 73 | 74 | //start 75 | for _, ser := range services { 76 | log.Info("start服务:%s", ser.GetName()) 77 | service.StartService(ser) 78 | } 79 | 80 | //service.run 81 | log.Info("run services") 82 | //for _, ser := range services { 83 | // log.Info("run服务:%s", ser.GetName()) 84 | // ser.GetPID().Tell(new(service.ServiceRun)) 85 | //} 86 | // 87 | 88 | // close 89 | c := make(chan os.Signal, 1) 90 | signal.Notify(c, os.Interrupt, os.Kill) 91 | sig := <-c 92 | log.Info("closing down (signal: %v)", sig) 93 | OnDestory() 94 | } 95 | 96 | func OnDestory() { 97 | for _, ser := range services { 98 | log.Info("destory服务:%s", ser.GetName()) 99 | ser.OnDestory() 100 | } 101 | for _, m := range modules { 102 | m.OnDestroy() 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /gateframework/agent.go: -------------------------------------------------------------------------------- 1 | package gateframework 2 | 3 | import ( 4 | "github.com/magicsea/ganet/log" 5 | "github.com/magicsea/ganet/network" 6 | "gameproto/msgs" 7 | "net" 8 | "reflect" 9 | 10 | "github.com/AsynkronIT/protoactor-go/actor" 11 | ) 12 | 13 | type NetType byte 14 | const ( 15 | TCP NetType = 0 16 | WEB_SOCKET NetType = 1 17 | ) 18 | 19 | type Agent interface { 20 | WriteMsg(msg []byte) 21 | LocalAddr() net.Addr 22 | RemoteAddr() net.Addr 23 | Close() 24 | Destroy() 25 | UserData() interface{} 26 | SetUserData(data interface{}) 27 | SetDead() 28 | GetNetType() NetType 29 | } 30 | 31 | type GFAgent struct { 32 | conn network.Conn 33 | gate *Gate 34 | agentActor *actor.PID 35 | userData interface{} 36 | dead bool 37 | netType NetType 38 | } 39 | func (a *GFAgent) GetNetType() NetType { 40 | return a.netType 41 | } 42 | func (a *GFAgent) SetDead() { 43 | a.dead = true 44 | } 45 | 46 | func (a *GFAgent) Run() { 47 | for { 48 | data, err := a.conn.ReadMsg() 49 | //log.Info("agent.read msg:", len(data)) 50 | if err != nil { 51 | log.Debug("read message: %v", err) 52 | break 53 | } 54 | 55 | if a.gate.Processor != nil { 56 | msg, err := a.gate.Processor.Unmarshal(data) 57 | if err != nil { 58 | log.Debug("unmarshal message error: %v", err) 59 | break 60 | } 61 | err = a.gate.Processor.Route(msg, a) 62 | if err != nil { 63 | log.Debug("route message error: %v", err) 64 | break 65 | } 66 | 67 | } else { 68 | //todo:not safe 69 | a.agentActor.Tell(&msgs.ReceviceClientMsg{data}) 70 | //if err != nil { 71 | // log.Error("ReceviceClientMsg message error: %v", err) 72 | // break 73 | //} 74 | } 75 | } 76 | } 77 | 78 | func (a *GFAgent) OnClose() { 79 | //todo:not safe 80 | if a.agentActor != nil && !a.dead { 81 | a.agentActor.Tell(&msgs.ClientDisconnect{}) 82 | } 83 | 84 | } 85 | 86 | func (a *GFAgent) WriteMsg(data []byte) { 87 | err := a.conn.WriteMsg(data) 88 | if err != nil { 89 | log.Error("write message %v error: %v", reflect.TypeOf(data), err) 90 | } 91 | 92 | } 93 | 94 | func (a *GFAgent) LocalAddr() net.Addr { 95 | return a.conn.LocalAddr() 96 | } 97 | 98 | func (a *GFAgent) RemoteAddr() net.Addr { 99 | return a.conn.RemoteAddr() 100 | } 101 | 102 | func (a *GFAgent) Close() { 103 | a.conn.Close() 104 | } 105 | 106 | func (a *GFAgent) Destroy() { 107 | a.conn.Destroy() 108 | 109 | } 110 | 111 | func (a *GFAgent) UserData() interface{} { 112 | return a.userData 113 | } 114 | 115 | func (a *GFAgent) SetUserData(data interface{}) { 116 | a.userData = data 117 | } 118 | -------------------------------------------------------------------------------- /mysqldb/dbclient.go: -------------------------------------------------------------------------------- 1 | package mysqldb 2 | 3 | import ( 4 | 5 | //"fmt" 6 | 7 | "github.com/astaxie/beego/orm" 8 | _ "github.com/go-sql-driver/mysql" 9 | ) 10 | 11 | type DBClient struct { 12 | ormDB orm.Ormer 13 | } 14 | 15 | func init() { 16 | orm.RegisterDriver("mysql", orm.DRMySQL) 17 | 18 | //orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8") 19 | } 20 | 21 | func RegDBModule(models ...interface{}) { 22 | orm.RegisterModel(models...) 23 | } 24 | 25 | //Start 注册和连接db dataSource连接信息 dbName数据库别名(不一定是数据库名) 26 | func ConnectDB(dataSource string, dbName string) (*DBClient, error) { 27 | err := orm.RegisterDataBase(dbName, "mysql", dataSource) 28 | if err != nil { 29 | return nil, err 30 | } 31 | o := orm.NewOrm() 32 | err2 := o.Using(dbName) 33 | if err2 != nil { 34 | return nil, err2 35 | } 36 | return &DBClient{o}, nil 37 | } 38 | 39 | //Insert 插入数据 40 | func (client *DBClient) Insert(obj interface{}) (int64, error) { 41 | //fmt.Println("####", client) 42 | //fmt.Println(client.ormDB, " ", obj) 43 | return client.ormDB.Insert(obj) 44 | } 45 | 46 | //Update 更新数据,cols更新列,默认所有 47 | func (client *DBClient) Update(md interface{}, cols ...string) (int64, error) { 48 | return client.ormDB.Update(md, cols...) 49 | } 50 | 51 | //InsertOrUpdate 52 | func (client *DBClient) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) { 53 | return client.ormDB.InsertOrUpdate(md, colConflitAndArgs...) 54 | } 55 | 56 | //Delete 删除数据,condCols删除条件,默认Id字段 57 | func (client *DBClient) Delete(md interface{}, condCols ...string) (int64, error) { 58 | return client.ormDB.Delete(md, condCols...) 59 | } 60 | 61 | //Read 有Cols用Cols做条件,没有,默认使用Id字段 62 | //norow没有结果 63 | func (client *DBClient) Read(md interface{}, cols ...string) (norow bool, e error) { 64 | e = client.ormDB.Read(md, cols...) 65 | norow = IsNoRow(e) 66 | return 67 | } 68 | 69 | //读取或者创建一行 70 | func (client *DBClient) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) { 71 | return client.ormDB.ReadOrCreate(md, col1, cols...) 72 | } 73 | 74 | //批量插入 75 | func (client *DBClient) InsertMulti(bulk int, mds interface{}) (int64, error) { 76 | return client.ormDB.InsertMulti(bulk, mds) 77 | } 78 | 79 | //raw1 80 | func (client *DBClient) Raw(query string, args ...interface{}) orm.RawSeter { 81 | return client.ormDB.Raw(query, args) 82 | } 83 | 84 | //报错解析 85 | func IsNoRow(e error) bool { 86 | return e == orm.ErrNoRows 87 | } 88 | 89 | //事物相关 90 | func (client *DBClient) Begin() error { 91 | return client.ormDB.Begin() 92 | } 93 | 94 | func (client *DBClient) Rollback() error { 95 | return client.ormDB.Rollback() 96 | } 97 | 98 | func (client *DBClient) Commit() error { 99 | return client.ormDB.Commit() 100 | } 101 | -------------------------------------------------------------------------------- /data-structures/hash-tables/ht.go: -------------------------------------------------------------------------------- 1 | // Implementation of a Hash Table with Separate Chaining 2 | // with linked lists using Horner's hash function 3 | // http://en.wikipedia.org/wiki/Hash_table#Separate_chaining_with_linked_lists 4 | package ht 5 | 6 | import ( 7 | "github.com/magicsea/ganet/data-structures/linked-list" 8 | "errors" 9 | "math" 10 | ) 11 | 12 | type HashTable struct { 13 | Table map[int]*list.List 14 | Size int 15 | Capacity int 16 | } 17 | 18 | type item struct { 19 | key string 20 | value interface{} 21 | } 22 | 23 | func New(cap int) *HashTable { 24 | table := make(map[int]*list.List, cap) 25 | return &HashTable{Table: table, Size: 0, Capacity: cap} 26 | } 27 | 28 | func (ht *HashTable) Get(key string) (interface{}, error) { 29 | index := ht.position(key) 30 | item, err := ht.find(index, key) 31 | 32 | if item == nil { 33 | return "", errors.New("Not Found") 34 | } 35 | 36 | return item.value, err 37 | } 38 | 39 | func (ht *HashTable) Put(key, value string) { 40 | index := ht.position(key) 41 | 42 | if ht.Table[index] == nil { 43 | ht.Table[index] = list.NewList() 44 | } 45 | 46 | item := &item{key: key, value: value} 47 | 48 | a, err := ht.find(index, key) 49 | if err != nil { 50 | // The key doesn't exist in HashTable 51 | ht.Table[index].Append(item) 52 | ht.Size++ 53 | } else { 54 | // The key exists so we overwrite its value 55 | a.value = value 56 | } 57 | } 58 | 59 | func (ht *HashTable) Del(key string) error { 60 | index := ht.position(key) 61 | l := ht.Table[index] 62 | var val *item 63 | 64 | l.Each(func(node list.Node) { 65 | if node.Value.(*item).key == key { 66 | val = node.Value.(*item) 67 | } 68 | }) 69 | 70 | if val == nil { 71 | return nil 72 | } 73 | 74 | ht.Size-- 75 | return l.Remove(val) 76 | } 77 | 78 | func (ht *HashTable) ForEach(f func(*item)) { 79 | for k := range ht.Table { 80 | if ht.Table[k] != nil { 81 | ht.Table[k].Each(func(node list.Node) { 82 | f(node.Value.(*item)) 83 | }) 84 | } 85 | } 86 | } 87 | 88 | func (ht *HashTable) position(s string) int { 89 | return hashCode(s) % ht.Capacity 90 | } 91 | 92 | func (ht *HashTable) find(i int, key string) (*item, error) { 93 | l := ht.Table[i] 94 | var val *item 95 | 96 | l.Each(func(node list.Node) { 97 | if node.Value.(*item).key == key { 98 | val = node.Value.(*item) 99 | } 100 | }) 101 | 102 | if val == nil { 103 | return nil, errors.New("Not Found") 104 | } 105 | 106 | return val, nil 107 | } 108 | 109 | // Horner's Method to hash string of length L (O(L)) 110 | func hashCode(s string) int { 111 | hash := int32(0) 112 | for i := 0; i < len(s); i++ { 113 | hash = int32(hash<<5-hash) + int32(s[i]) 114 | hash &= hash 115 | } 116 | return int(math.Abs(float64(hash))) 117 | } 118 | -------------------------------------------------------------------------------- /service/service.go: -------------------------------------------------------------------------------- 1 | /* 2 | **服务类型,可作为独立进程或线程使用 3 | ** 4 | */ 5 | package service 6 | 7 | import ( 8 | "fmt" 9 | 10 | "reflect" 11 | 12 | "github.com/magicsea/ganet/log" 13 | 14 | "github.com/AsynkronIT/protoactor-go/actor" 15 | "github.com/AsynkronIT/protoactor-go/remote" 16 | ) 17 | 18 | type Context actor.Context 19 | 20 | type IService interface { 21 | IServiceData 22 | //Receive(context actor.Context) 23 | OnReceive(context Context) 24 | OnInit() 25 | OnStart(as *ActorService) 26 | //正式运行(服务线程) 27 | OnRun() 28 | 29 | OnDestory() 30 | } 31 | 32 | type ServiceRun struct { 33 | } 34 | 35 | //interface 36 | //func (s *BaseServer) OnReceive(context Context) {} 37 | //func (s *BaseServer) OnInit() {} 38 | //func (s *BaseServer) OnStart() {} 39 | 40 | type MessageFunc func(context Context) 41 | 42 | //服务的代理 43 | type ActorService struct { 44 | serviceIns IService 45 | rounter map[reflect.Type]MessageFunc 46 | } 47 | 48 | func (s *ActorService) Receive(context actor.Context) { 49 | //switch msg := context.Message().(type) { 50 | //case *hello: 51 | // fmt.Printf("Hello %v\n", msg.Who) 52 | //} 53 | switch msg := context.Message().(type) { 54 | case *actor.Started: 55 | fmt.Println("Started, initialize actor here:",s.serviceIns.GetName()) 56 | s.serviceIns.SetPID(context.Self()) 57 | s.serviceIns.OnStart(s) 58 | s.serviceIns.OnRun() 59 | case *actor.Stopping: 60 | fmt.Println("Stopping, actor is about shut down") 61 | case *actor.Stopped: 62 | fmt.Println("Stopped, actor and its children are stopped") 63 | case *actor.Restarting: 64 | fmt.Println("Restarting, actor is about restart") 65 | case *ServiceRun: 66 | fmt.Println("ServiceRun ", s.serviceIns.GetName()) 67 | //s.serviceIns.OnRun() 68 | default: 69 | log.Debug("recv defalult:", msg) 70 | s.serviceIns.OnReceive(context.(Context)) 71 | fun := s.rounter[reflect.TypeOf(msg)] 72 | if fun != nil { 73 | fun(context.(Context)) 74 | } 75 | } 76 | } 77 | 78 | func (s *ActorService) RegisterMsg(t reflect.Type, f MessageFunc) { 79 | s.rounter[t] = f 80 | } 81 | 82 | func StartService(s IService) { 83 | ac := &ActorService{s, make(map[reflect.Type]MessageFunc)} 84 | 85 | // decider := func(reason interface{}) actor.Directive { 86 | // log.Error("handling failure for child:%v", reason) 87 | // return actor.StopDirective 88 | // } 89 | // supervisor := actor.NewOneForOneStrategy(10, 1000, decider) 90 | 91 | props := actor.FromProducer(func() actor.Actor { return ac }) //.WithSupervisor(supervisor) 92 | //props := actor.FromInstance(ac) 93 | if s.GetAddress() != "" { 94 | remote.Start(s.GetAddress()) 95 | } 96 | _, err := actor.SpawnNamed(props, s.GetName()) 97 | if err == nil { 98 | //s.SetPID(pid) 99 | //s.OnStart(ac) 100 | } else { 101 | log.Error("#############actor.SpawnNamed error:%v", err) 102 | } 103 | 104 | } 105 | 106 | func DestoryService(s *ActorService) { 107 | s.serviceIns.OnDestory() 108 | } 109 | -------------------------------------------------------------------------------- /gateframework/gate.go: -------------------------------------------------------------------------------- 1 | package gateframework 2 | 3 | import ( 4 | "github.com/magicsea/ganet/network" 5 | _ "net" 6 | _ "reflect" 7 | "time" 8 | 9 | "github.com/AsynkronIT/protoactor-go/actor" 10 | "github.com/magicsea/ganet/log" 11 | ) 12 | 13 | type IGateService interface { 14 | GetAgentActor(Agent) (*actor.PID, error) 15 | } 16 | 17 | type Gate struct { 18 | MaxConnNum int 19 | PendingWriteNum int 20 | MaxMsgLen uint32 21 | Processor network.Processor 22 | //AgentChanRPC *chanrpc.Server 23 | 24 | // websocket 25 | WSAddr string 26 | HTTPTimeout time.Duration 27 | CertFile string 28 | KeyFile string 29 | 30 | // tcp 31 | TCPAddr string 32 | LenMsgLen int 33 | LittleEndian bool 34 | 35 | //实例 36 | wsServer *network.WSServer 37 | tcpServer *network.TCPServer 38 | } 39 | 40 | func (gate *Gate) Run(gs IGateService) { 41 | 42 | var wsServer *network.WSServer 43 | if gate.WSAddr != "" { 44 | wsServer = new(network.WSServer) 45 | wsServer.Addr = gate.WSAddr 46 | wsServer.MaxConnNum = gate.MaxConnNum 47 | wsServer.PendingWriteNum = gate.PendingWriteNum 48 | wsServer.MaxMsgLen = gate.MaxMsgLen 49 | wsServer.HTTPTimeout = gate.HTTPTimeout 50 | wsServer.CertFile = gate.CertFile 51 | wsServer.KeyFile = gate.KeyFile 52 | wsServer.NewAgent = func(conn *network.WSConn) network.Agent { 53 | a := &GFAgent{conn: conn, gate: gate, netType: WEB_SOCKET} 54 | //if gate.AgentChanRPC != nil { 55 | // gate.AgentChanRPC.Go("NewAgent", a) 56 | //} 57 | ac, err := gs.GetAgentActor(a) 58 | if err != nil { 59 | //todo:应该不会发生吧 60 | log.Error("NewAgent fail:%v", err.Error()) 61 | } 62 | a.agentActor = ac 63 | return a 64 | } 65 | } 66 | 67 | var tcpServer *network.TCPServer 68 | if gate.TCPAddr != "" { 69 | tcpServer = new(network.TCPServer) 70 | tcpServer.Addr = gate.TCPAddr 71 | tcpServer.MaxConnNum = gate.MaxConnNum 72 | tcpServer.PendingWriteNum = gate.PendingWriteNum 73 | tcpServer.LenMsgLen = gate.LenMsgLen 74 | tcpServer.MaxMsgLen = gate.MaxMsgLen 75 | tcpServer.LittleEndian = gate.LittleEndian 76 | tcpServer.NewAgent = func(conn *network.TCPConn) network.Agent { 77 | a := &GFAgent{conn: conn, gate: gate, netType: TCP} 78 | //ab := NewAgentActor(a, pid) 79 | //gs.Pid.Tell(new(messages.NewChild)) //请求一个actor 80 | //a.agentActor = <-gs.actorchan 81 | //a.agentActor.bindAgent = a 82 | ac, err := gs.GetAgentActor(a) 83 | if err != nil { 84 | //todo:应该不会发生吧 85 | log.Error("NewAgent fail:%v", err.Error()) 86 | } 87 | a.agentActor = ac 88 | return a 89 | } 90 | } 91 | 92 | if wsServer != nil { 93 | wsServer.Start() 94 | } 95 | if tcpServer != nil { 96 | tcpServer.Start() 97 | } 98 | 99 | gate.tcpServer = tcpServer 100 | gate.wsServer = wsServer 101 | } 102 | 103 | func (gate *Gate) OnDestroy() { 104 | if gate.wsServer != nil { 105 | gate.wsServer.Close() 106 | } 107 | if gate.tcpServer != nil { 108 | gate.tcpServer.Close() 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /data-structures/binary-tree/bst.go: -------------------------------------------------------------------------------- 1 | package bst 2 | 3 | import () 4 | 5 | type Node struct { 6 | Value int 7 | Parent *Node 8 | Left *Node 9 | Right *Node 10 | } 11 | 12 | func NewNode(i int) *Node { 13 | return &Node{Value: i} 14 | } 15 | 16 | func (n *Node) Compare(m *Node) int { 17 | if n.Value < m.Value { 18 | return -1 19 | } else if n.Value > m.Value { 20 | return 1 21 | } else { 22 | return 0 23 | } 24 | } 25 | 26 | type Tree struct { 27 | Head *Node 28 | Size int 29 | } 30 | 31 | func NewTree(n *Node) *Tree { 32 | if n == nil { 33 | return &Tree{} 34 | } 35 | return &Tree{Head: n, Size: 1} 36 | } 37 | 38 | func (t *Tree) Insert(i int) { 39 | n := &Node{Value: i} 40 | if t.Head == nil { 41 | t.Head = n 42 | t.Size++ 43 | return 44 | } 45 | 46 | h := t.Head 47 | 48 | for { 49 | if n.Compare(h) == -1 { 50 | if h.Left == nil { 51 | h.Left = n 52 | n.Parent = h 53 | break 54 | } else { 55 | h = h.Left 56 | } 57 | } else { 58 | if h.Right == nil { 59 | h.Right = n 60 | n.Parent = h 61 | break 62 | } else { 63 | h = h.Right 64 | } 65 | } 66 | } 67 | t.Size++ 68 | } 69 | 70 | func (t *Tree) Search(i int) *Node { 71 | h := t.Head 72 | n := &Node{Value: i} 73 | 74 | for h != nil { 75 | switch h.Compare(n) { 76 | case -1: 77 | h = h.Right 78 | case 1: 79 | h = h.Left 80 | case 0: 81 | return h 82 | default: 83 | panic("Node not found") 84 | } 85 | } 86 | panic("Node not found") 87 | } 88 | 89 | // returns true if a node with value i was found 90 | // and deleted and returns false otherwise 91 | func (t *Tree) Delete(i int) bool { 92 | var parent *Node 93 | 94 | h := t.Head 95 | n := &Node{Value: i} 96 | for h != nil { 97 | switch n.Compare(h) { 98 | case -1: 99 | parent = h 100 | h = h.Left 101 | case 1: 102 | parent = h 103 | h = h.Right 104 | case 0: 105 | if h.Left != nil { 106 | right := h.Right 107 | h.Value = h.Left.Value 108 | h.Left = h.Left.Left 109 | h.Right = h.Left.Right 110 | 111 | if right != nil { 112 | subTree := &Tree{Head: h} 113 | IterOnTree(right, func(n *Node) { 114 | subTree.Insert(n.Value) 115 | }) 116 | } 117 | t.Size-- 118 | return true 119 | } 120 | 121 | if h.Right != nil { 122 | h.Value = h.Right.Value 123 | h.Left = h.Right.Left 124 | h.Right = h.Right.Right 125 | 126 | t.Size-- 127 | return true 128 | } 129 | 130 | if parent == nil { 131 | t.Head = nil 132 | t.Size-- 133 | return true 134 | } 135 | 136 | if parent.Left == n { 137 | parent.Left = nil 138 | } else { 139 | parent.Right = nil 140 | } 141 | t.Size-- 142 | return true 143 | } 144 | } 145 | return false 146 | } 147 | 148 | func IterOnTree(n *Node, f func(*Node)) bool { 149 | if n == nil { 150 | return true 151 | } 152 | if !IterOnTree(n.Left, f) { 153 | return false 154 | } 155 | 156 | f(n) 157 | 158 | return IterOnTree(n.Right, f) 159 | } 160 | -------------------------------------------------------------------------------- /network/ws_conn.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "github.com/magicsea/ganet/log" 5 | "errors" 6 | "net" 7 | "sync" 8 | 9 | "github.com/gorilla/websocket" 10 | ) 11 | 12 | type WebsocketConnSet map[*websocket.Conn]struct{} 13 | 14 | type WSConn struct { 15 | sync.Mutex 16 | conn *websocket.Conn 17 | writeChan chan []byte 18 | maxMsgLen uint32 19 | closeFlag bool 20 | } 21 | 22 | func newWSConn(conn *websocket.Conn, pendingWriteNum int, maxMsgLen uint32) *WSConn { 23 | wsConn := new(WSConn) 24 | wsConn.conn = conn 25 | wsConn.writeChan = make(chan []byte, pendingWriteNum) 26 | wsConn.maxMsgLen = maxMsgLen 27 | 28 | go func() { 29 | for b := range wsConn.writeChan { 30 | if b == nil { 31 | break 32 | } 33 | 34 | err := conn.WriteMessage(websocket.BinaryMessage, b) 35 | if err != nil { 36 | break 37 | } 38 | } 39 | 40 | conn.Close() 41 | wsConn.Lock() 42 | wsConn.closeFlag = true 43 | wsConn.Unlock() 44 | }() 45 | 46 | return wsConn 47 | } 48 | 49 | func (wsConn *WSConn) doDestroy() { 50 | wsConn.conn.UnderlyingConn().(*net.TCPConn).SetLinger(0) 51 | wsConn.conn.Close() 52 | 53 | if !wsConn.closeFlag { 54 | close(wsConn.writeChan) 55 | wsConn.closeFlag = true 56 | } 57 | } 58 | 59 | func (wsConn *WSConn) Destroy() { 60 | wsConn.Lock() 61 | defer wsConn.Unlock() 62 | 63 | wsConn.doDestroy() 64 | } 65 | 66 | func (wsConn *WSConn) Close() { 67 | wsConn.Lock() 68 | defer wsConn.Unlock() 69 | if wsConn.closeFlag { 70 | return 71 | } 72 | 73 | wsConn.doWrite(nil) 74 | wsConn.closeFlag = true 75 | } 76 | 77 | func (wsConn *WSConn) doWrite(b []byte) { 78 | if len(wsConn.writeChan) == cap(wsConn.writeChan) { 79 | log.Debug("close conn: channel full") 80 | wsConn.doDestroy() 81 | return 82 | } 83 | 84 | wsConn.writeChan <- b 85 | } 86 | 87 | func (wsConn *WSConn) LocalAddr() net.Addr { 88 | return wsConn.conn.LocalAddr() 89 | } 90 | 91 | func (wsConn *WSConn) RemoteAddr() net.Addr { 92 | return wsConn.conn.RemoteAddr() 93 | } 94 | 95 | // goroutine not safe 96 | func (wsConn *WSConn) ReadMsg() ([]byte, error) { 97 | _, b, err := wsConn.conn.ReadMessage() 98 | return b, err 99 | } 100 | 101 | // args must not be modified by the others goroutines 102 | func (wsConn *WSConn) WriteMsg(args ...[]byte) error { 103 | wsConn.Lock() 104 | defer wsConn.Unlock() 105 | if wsConn.closeFlag { 106 | return nil 107 | } 108 | 109 | // get len 110 | var msgLen uint32 111 | for i := 0; i < len(args); i++ { 112 | msgLen += uint32(len(args[i])) 113 | } 114 | 115 | // check len 116 | if msgLen > wsConn.maxMsgLen { 117 | return errors.New("message too long") 118 | } else if msgLen < 1 { 119 | return errors.New("message too short") 120 | } 121 | 122 | // don't copy 123 | if len(args) == 1 { 124 | wsConn.doWrite(args[0]) 125 | return nil 126 | } 127 | 128 | // merge the args 129 | msg := make([]byte, msgLen) 130 | l := 0 131 | for i := 0; i < len(args); i++ { 132 | copy(msg[l:], args[i]) 133 | l += len(args[i]) 134 | } 135 | 136 | wsConn.doWrite(msg) 137 | 138 | return nil 139 | } 140 | -------------------------------------------------------------------------------- /data-structures/graph/graph_test.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestUndirectedGraph(t *testing.T) { 9 | g := NewUndirected() 10 | 11 | for i := 0; i < 10; i++ { 12 | v := VertexId(i) 13 | g.AddVertex(v) 14 | } 15 | 16 | if len(g.edges) != 10 { 17 | fmt.Println(g) 18 | t.Error() 19 | } 20 | 21 | for i := 0; i < 10; i++ { 22 | g.AddEdge(VertexId(i), VertexId(i%2), 1) 23 | } 24 | 25 | if g.IsEdge(0, 8) == false || g.IsEdge(0, 9) == true || g.CheckVertex(2) != true { 26 | fmt.Println(g) 27 | t.Error() 28 | } 29 | 30 | // AddEdge should fail for already existing Edge 31 | err := g.AddEdge(0, 2, 1) 32 | if err == nil { 33 | fmt.Println(g) 34 | t.Error() 35 | } 36 | 37 | // AddVertex should fail for already existing vertex 38 | err = g.AddVertex(0) 39 | if err == nil { 40 | fmt.Println(g) 41 | t.Error() 42 | } 43 | 44 | g.RemoveVertex(VertexId(9)) 45 | 46 | if g.IsVertex(VertexId(9)) { 47 | fmt.Println(g.edges[9] == nil) 48 | t.Error() 49 | } 50 | 51 | // RemoveVertex should fail for unknown vertex 52 | err = g.RemoveVertex(VertexId(9)) 53 | 54 | if err == nil { 55 | fmt.Println(g.edges[9] == nil) 56 | t.Error() 57 | } 58 | 59 | g.RemoveEdge(0, 8) 60 | 61 | if g.IsEdge(VertexId(0), VertexId(8)) == true || g.edgesCount != 7 { 62 | fmt.Println(g.IsEdge(VertexId(0), VertexId(8)), g.edgesCount) 63 | t.Error() 64 | } 65 | 66 | // RemoveEdge should fail for unknown egde 67 | err = g.RemoveEdge(0, 8) 68 | 69 | if err == nil { 70 | fmt.Println(g) 71 | t.Error() 72 | } 73 | 74 | c := g.EdgesIter() 75 | 76 | countEdge := 0 77 | for _ = range c { 78 | countEdge++ 79 | } 80 | 81 | if g.EdgesCount() != countEdge { 82 | t.Error() 83 | } 84 | 85 | d := g.VerticesIter() 86 | verticesCount := g.Order() 87 | countVertices := 0 88 | 89 | for _ = range d { 90 | countVertices++ 91 | } 92 | 93 | if countVertices != verticesCount { 94 | fmt.Println(countVertices, g.edges) 95 | t.Error() 96 | } 97 | 98 | g.TouchVertex(9) 99 | if _, ok := g.edges[9]; !ok { 100 | t.Error() 101 | } 102 | } 103 | 104 | func TestDirectedGraph(t *testing.T) { 105 | g := NewDirected() 106 | 107 | for i := 0; i < 10; i++ { 108 | g.AddVertex(VertexId(i)) 109 | } 110 | 111 | if len(g.edges) != 10 { 112 | fmt.Println(g) 113 | t.Error() 114 | } 115 | 116 | for i := 0; i < 10; i++ { 117 | g.AddEdge(VertexId(i), VertexId(i%2), 1) 118 | } 119 | 120 | r := g.Reverse() 121 | if !r.IsEdge(1, 7) || r.IsEdge(8, 0) { 122 | fmt.Println(r.edges) 123 | t.Error() 124 | } 125 | 126 | successors := r.GetSuccessors(1).VerticesIter() 127 | for successor := range successors { 128 | if successor != 3 && 129 | successor != 5 && 130 | successor != 7 && 131 | successor != 9 { 132 | t.Error() 133 | } 134 | } 135 | 136 | predecessors := g.GetPredecessors(1).VerticesIter() 137 | for predecessor := range predecessors { 138 | if predecessor != 3 && 139 | predecessor != 5 && 140 | predecessor != 7 && 141 | predecessor != 9 { 142 | t.Error() 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /network/tcp_server.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "github.com/magicsea/ganet/log" 5 | "fmt" 6 | "net" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | type TCPServer struct { 12 | Addr string 13 | MaxConnNum int 14 | PendingWriteNum int 15 | NewAgent func(*TCPConn) Agent 16 | ln net.Listener 17 | conns ConnSet 18 | mutexConns sync.Mutex 19 | wgLn sync.WaitGroup 20 | wgConns sync.WaitGroup 21 | 22 | // msg parser 23 | LenMsgLen int 24 | MinMsgLen uint32 25 | MaxMsgLen uint32 26 | LittleEndian bool 27 | msgParser *MsgParser 28 | } 29 | 30 | func (server *TCPServer) Start() { 31 | server.init() 32 | go server.run() 33 | } 34 | 35 | func (server *TCPServer) init() { 36 | ln, err := net.Listen("tcp", server.Addr) 37 | if err != nil { 38 | log.Fatal("%v", err) 39 | } 40 | 41 | if server.MaxConnNum <= 0 { 42 | server.MaxConnNum = 100 43 | log.Info("invalid MaxConnNum, reset to %v", server.MaxConnNum) 44 | } 45 | if server.PendingWriteNum <= 0 { 46 | server.PendingWriteNum = 100 47 | log.Info("invalid PendingWriteNum, reset to %v", server.PendingWriteNum) 48 | } 49 | if server.NewAgent == nil { 50 | log.Fatal("NewAgent must not be nil") 51 | } 52 | 53 | server.ln = ln 54 | server.conns = make(ConnSet) 55 | 56 | // msg parser 57 | msgParser := NewMsgParser() 58 | msgParser.SetMsgLen(server.LenMsgLen, server.MinMsgLen, server.MaxMsgLen) 59 | msgParser.SetByteOrder(server.LittleEndian) 60 | server.msgParser = msgParser 61 | } 62 | 63 | func (server *TCPServer) run() { 64 | server.wgLn.Add(1) 65 | defer server.wgLn.Done() 66 | 67 | var tempDelay time.Duration 68 | for { 69 | conn, err := server.ln.Accept() 70 | if err != nil { 71 | if ne, ok := err.(net.Error); ok && ne.Temporary() { 72 | if tempDelay == 0 { 73 | tempDelay = 5 * time.Millisecond 74 | } else { 75 | tempDelay *= 2 76 | } 77 | if max := 1 * time.Second; tempDelay > max { 78 | tempDelay = max 79 | } 80 | log.Info("accept error: %v; retrying in %v", err, tempDelay) 81 | time.Sleep(tempDelay) 82 | continue 83 | } 84 | return 85 | } 86 | tempDelay = 0 87 | 88 | server.mutexConns.Lock() 89 | if len(server.conns) >= server.MaxConnNum { 90 | server.mutexConns.Unlock() 91 | conn.Close() 92 | log.Debug("too many connections") 93 | continue 94 | } 95 | server.conns[conn] = struct{}{} 96 | server.mutexConns.Unlock() 97 | 98 | server.wgConns.Add(1) 99 | 100 | tcpConn := newTCPConn(conn, server.PendingWriteNum, server.msgParser) 101 | fmt.Println("new conn from ", tcpConn.RemoteAddr()) 102 | agent := server.NewAgent(tcpConn) 103 | go func() { 104 | agent.Run() 105 | 106 | // cleanup 107 | tcpConn.Close() 108 | server.mutexConns.Lock() 109 | delete(server.conns, conn) 110 | server.mutexConns.Unlock() 111 | agent.OnClose() 112 | 113 | server.wgConns.Done() 114 | }() 115 | } 116 | } 117 | 118 | func (server *TCPServer) Close() { 119 | server.ln.Close() 120 | server.wgLn.Wait() 121 | 122 | server.mutexConns.Lock() 123 | for conn := range server.conns { 124 | conn.Close() 125 | } 126 | server.conns = nil 127 | server.mutexConns.Unlock() 128 | server.wgConns.Wait() 129 | } 130 | -------------------------------------------------------------------------------- /network/ws_client.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | 7 | "github.com/magicsea/ganet/log" 8 | 9 | "github.com/gorilla/websocket" 10 | ) 11 | 12 | type WSClient struct { 13 | sync.Mutex 14 | Addr string 15 | ConnNum int 16 | ConnectInterval time.Duration 17 | PendingWriteNum int 18 | MaxMsgLen uint32 19 | HandshakeTimeout time.Duration 20 | AutoReconnect bool 21 | NewAgent func(Conn) Agent 22 | dialer websocket.Dialer 23 | conns WebsocketConnSet 24 | wg sync.WaitGroup 25 | closeFlag bool 26 | } 27 | 28 | func (client *WSClient) Set(addr string, newAgentFunc func(Conn) Agent) { 29 | client.Addr = addr 30 | client.NewAgent = newAgentFunc 31 | } 32 | 33 | func (client *WSClient) Start() { 34 | client.init() 35 | 36 | for i := 0; i < client.ConnNum; i++ { 37 | client.wg.Add(1) 38 | go client.connect() 39 | } 40 | } 41 | 42 | func (client *WSClient) init() { 43 | client.Lock() 44 | defer client.Unlock() 45 | 46 | if client.ConnNum <= 0 { 47 | client.ConnNum = 1 48 | log.Info("invalid ConnNum, reset to %v", client.ConnNum) 49 | } 50 | if client.ConnectInterval <= 0 { 51 | client.ConnectInterval = 3 * time.Second 52 | log.Info("invalid ConnectInterval, reset to %v", client.ConnectInterval) 53 | } 54 | if client.PendingWriteNum <= 0 { 55 | client.PendingWriteNum = 100 56 | log.Info("invalid PendingWriteNum, reset to %v", client.PendingWriteNum) 57 | } 58 | if client.MaxMsgLen <= 0 { 59 | client.MaxMsgLen = 4096 60 | log.Info("invalid MaxMsgLen, reset to %v", client.MaxMsgLen) 61 | } 62 | if client.HandshakeTimeout <= 0 { 63 | client.HandshakeTimeout = 10 * time.Second 64 | log.Info("invalid HandshakeTimeout, reset to %v", client.HandshakeTimeout) 65 | } 66 | if client.NewAgent == nil { 67 | log.Fatal("NewAgent must not be nil") 68 | } 69 | if client.conns != nil { 70 | log.Fatal("client is running") 71 | } 72 | 73 | client.conns = make(WebsocketConnSet) 74 | client.closeFlag = false 75 | client.dialer = websocket.Dialer{ 76 | HandshakeTimeout: client.HandshakeTimeout, 77 | } 78 | } 79 | 80 | func (client *WSClient) dial() *websocket.Conn { 81 | for { 82 | conn, _, err := client.dialer.Dial(client.Addr, nil) 83 | if err == nil || client.closeFlag { 84 | return conn 85 | } 86 | 87 | log.Info("connect to [%v] error: %v", client.Addr, err) 88 | time.Sleep(client.ConnectInterval) 89 | continue 90 | } 91 | } 92 | 93 | func (client *WSClient) connect() { 94 | defer client.wg.Done() 95 | 96 | reconnect: 97 | conn := client.dial() 98 | if conn == nil { 99 | return 100 | } 101 | conn.SetReadLimit(int64(client.MaxMsgLen)) 102 | 103 | client.Lock() 104 | if client.closeFlag { 105 | client.Unlock() 106 | conn.Close() 107 | return 108 | } 109 | client.conns[conn] = struct{}{} 110 | client.Unlock() 111 | 112 | wsConn := newWSConn(conn, client.PendingWriteNum, client.MaxMsgLen) 113 | agent := client.NewAgent(wsConn) 114 | agent.Run() 115 | 116 | // cleanup 117 | wsConn.Close() 118 | client.Lock() 119 | delete(client.conns, conn) 120 | client.Unlock() 121 | agent.OnClose() 122 | 123 | if client.AutoReconnect { 124 | time.Sleep(client.ConnectInterval) 125 | goto reconnect 126 | } 127 | } 128 | 129 | func (client *WSClient) Close() { 130 | client.Lock() 131 | client.closeFlag = true 132 | for conn := range client.conns { 133 | conn.Close() 134 | } 135 | client.conns = nil 136 | client.Unlock() 137 | 138 | client.wg.Wait() 139 | } 140 | -------------------------------------------------------------------------------- /network/tcp_client.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "sync" 7 | "time" 8 | 9 | "github.com/magicsea/ganet/log" 10 | ) 11 | 12 | type INetClient interface { 13 | Set(addr string, newAgentFunc func(Conn) Agent) 14 | Start() 15 | } 16 | 17 | type TCPClient struct { 18 | sync.Mutex 19 | Addr string 20 | ConnNum int 21 | ConnectInterval time.Duration 22 | PendingWriteNum int 23 | AutoReconnect bool 24 | NewAgent func(Conn) Agent 25 | conns ConnSet 26 | wg sync.WaitGroup 27 | closeFlag bool 28 | 29 | // msg parser 30 | LenMsgLen int 31 | MinMsgLen uint32 32 | MaxMsgLen uint32 33 | LittleEndian bool 34 | msgParser *MsgParser 35 | } 36 | 37 | func (client *TCPClient) Set(addr string, newAgentFunc func(Conn) Agent) { 38 | client.Addr = addr 39 | client.NewAgent = newAgentFunc 40 | } 41 | 42 | func (client *TCPClient) Start() { 43 | fmt.Println("TCPClient init... ", client.ConnNum) 44 | client.init() 45 | fmt.Println("will conn ", client.ConnNum) 46 | for i := 0; i < client.ConnNum; i++ { 47 | client.wg.Add(1) 48 | go client.connect() 49 | } 50 | } 51 | 52 | func (client *TCPClient) init() { 53 | client.Lock() 54 | defer client.Unlock() 55 | 56 | if client.ConnNum <= 0 { 57 | client.ConnNum = 1 58 | log.Info("invalid ConnNum, reset to %v", client.ConnNum) 59 | } 60 | if client.ConnectInterval <= 0 { 61 | client.ConnectInterval = 3 * time.Second 62 | log.Info("invalid ConnectInterval, reset to %v", client.ConnectInterval) 63 | } 64 | if client.PendingWriteNum <= 0 { 65 | client.PendingWriteNum = 100 66 | log.Info("invalid PendingWriteNum, reset to %v", client.PendingWriteNum) 67 | } 68 | if client.NewAgent == nil { 69 | log.Fatal("NewAgent must not be nil") 70 | } 71 | if client.conns != nil { 72 | log.Fatal("client is running") 73 | } 74 | 75 | client.conns = make(ConnSet) 76 | client.closeFlag = false 77 | 78 | // msg parser 79 | msgParser := NewMsgParser() 80 | msgParser.SetMsgLen(client.LenMsgLen, client.MinMsgLen, client.MaxMsgLen) 81 | msgParser.SetByteOrder(client.LittleEndian) 82 | client.msgParser = msgParser 83 | } 84 | 85 | func (client *TCPClient) dial() net.Conn { 86 | for { 87 | conn, err := net.Dial("tcp", client.Addr) 88 | if err == nil || client.closeFlag { 89 | return conn 90 | } 91 | 92 | log.Info("connect to %v error: %v", client.Addr, err) 93 | time.Sleep(client.ConnectInterval) 94 | continue 95 | } 96 | } 97 | 98 | func (client *TCPClient) connect() { 99 | defer client.wg.Done() 100 | fmt.Println("tcp connect...") 101 | reconnect: 102 | conn := client.dial() 103 | if conn == nil { 104 | fmt.Println("tcp dial fail") 105 | return 106 | } 107 | 108 | client.Lock() 109 | if client.closeFlag { 110 | client.Unlock() 111 | conn.Close() 112 | fmt.Println("tcp will close") 113 | return 114 | } 115 | client.conns[conn] = struct{}{} 116 | client.Unlock() 117 | fmt.Println("tcp connected") 118 | tcpConn := newTCPConn(conn, client.PendingWriteNum, client.msgParser) 119 | agent := client.NewAgent(tcpConn) 120 | agent.Run() 121 | 122 | // cleanup 123 | tcpConn.Close() 124 | client.Lock() 125 | delete(client.conns, conn) 126 | client.Unlock() 127 | agent.OnClose() 128 | 129 | if client.AutoReconnect { 130 | time.Sleep(client.ConnectInterval) 131 | goto reconnect 132 | } 133 | } 134 | 135 | func (client *TCPClient) Close() { 136 | client.Lock() 137 | client.closeFlag = true 138 | for conn := range client.conns { 139 | conn.Close() 140 | } 141 | client.conns = nil 142 | client.Unlock() 143 | 144 | client.wg.Wait() 145 | } 146 | -------------------------------------------------------------------------------- /data-structures/linked-list/linked_list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | type List struct { 8 | Length int 9 | Head *Node 10 | Tail *Node 11 | } 12 | 13 | func NewList() *List { 14 | l := new(List) 15 | l.Length = 0 16 | return l 17 | } 18 | 19 | type Node struct { 20 | Value interface{} 21 | Prev *Node 22 | Next *Node 23 | } 24 | 25 | func NewNode(value interface{}) *Node { 26 | return &Node{Value: value} 27 | } 28 | 29 | func (l *List) Len() int { 30 | return l.Length 31 | } 32 | 33 | func (l *List) IsEmpty() bool { 34 | return l.Length == 0 35 | } 36 | 37 | func (l *List) Prepend(value interface{}) { 38 | node := NewNode(value) 39 | if l.Len() == 0 { 40 | l.Head = node 41 | l.Tail = l.Head 42 | } else { 43 | formerHead := l.Head 44 | formerHead.Prev = node 45 | 46 | node.Next = formerHead 47 | l.Head = node 48 | } 49 | 50 | l.Length++ 51 | } 52 | 53 | func (l *List) Append(value interface{}) { 54 | node := NewNode(value) 55 | 56 | if l.Len() == 0 { 57 | l.Head = node 58 | l.Tail = l.Head 59 | } else { 60 | formerTail := l.Tail 61 | formerTail.Next = node 62 | 63 | node.Prev = formerTail 64 | l.Tail = node 65 | } 66 | 67 | l.Length++ 68 | } 69 | 70 | func (l *List) Add(value interface{}, index int) error { 71 | if index > l.Len() { 72 | return errors.New("Index out of range") 73 | } 74 | 75 | node := NewNode(value) 76 | 77 | if l.Len() == 0 || index == 0 { 78 | l.Prepend(value) 79 | return nil 80 | } 81 | 82 | if l.Len()-1 == index { 83 | l.Append(value) 84 | return nil 85 | } 86 | 87 | nextNode, _ := l.Get(index) 88 | prevNode := nextNode.Prev 89 | 90 | prevNode.Next = node 91 | node.Prev = prevNode 92 | 93 | nextNode.Prev = node 94 | node.Next = nextNode 95 | 96 | l.Length++ 97 | 98 | return nil 99 | } 100 | 101 | func (l *List) Remove(value interface{}) error { 102 | if l.Len() == 0 { 103 | return errors.New("Empty list") 104 | } 105 | 106 | if l.Head.Value == value { 107 | l.Head = l.Head.Next 108 | l.Length-- 109 | return nil 110 | } 111 | 112 | found := 0 113 | for n := l.Head; n != nil; n = n.Next { 114 | 115 | if *n.Value.(*Node) == value && found == 0 { 116 | n.Next.Prev, n.Prev.Next = n.Prev, n.Next 117 | l.Length-- 118 | found++ 119 | } 120 | } 121 | 122 | if found == 0 { 123 | return errors.New("Node not found") 124 | } 125 | 126 | return nil 127 | } 128 | 129 | func (l *List) Get(index int) (*Node, error) { 130 | if index > l.Len() { 131 | return nil, errors.New("Index out of range") 132 | } 133 | 134 | node := l.Head 135 | for i := 0; i < index; i++ { 136 | node = node.Next 137 | } 138 | 139 | return node, nil 140 | } 141 | 142 | func (l *List) Find(node *Node) (int, error) { 143 | if l.Len() == 0 { 144 | return 0, errors.New("Empty list") 145 | } 146 | 147 | index := 0 148 | found := -1 149 | l.Map(func(n *Node) { 150 | index++ 151 | if n.Value == node.Value && found == -1 { 152 | found = index 153 | } 154 | }) 155 | 156 | if found == -1 { 157 | return 0, errors.New("Item not found") 158 | } 159 | 160 | return found, nil 161 | } 162 | 163 | func (l *List) Clear() { 164 | l.Length = 0 165 | l.Head = nil 166 | l.Tail = nil 167 | } 168 | 169 | func (l *List) Concat(k *List) { 170 | l.Tail.Next, k.Head.Prev = k.Head, l.Tail 171 | l.Tail = k.Tail 172 | l.Length += k.Length 173 | } 174 | 175 | func (list *List) Map(f func(node *Node)) { 176 | for node := list.Head; node != nil; node = node.Next { 177 | n := node.Value.(*Node) 178 | f(n) 179 | } 180 | } 181 | 182 | func (list *List) Each(f func(node Node)) { 183 | for node := list.Head; node != nil; node = node.Next { 184 | f(*node) 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /network/tcp_msg.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | "fmt" 7 | "io" 8 | "math" 9 | ) 10 | 11 | // -------------- 12 | // | len | data | 13 | // -------------- 14 | type MsgParser struct { 15 | lenMsgLen int 16 | minMsgLen uint32 17 | maxMsgLen uint32 18 | littleEndian bool 19 | } 20 | 21 | func NewMsgParser() *MsgParser { 22 | p := new(MsgParser) 23 | p.lenMsgLen = 2 24 | p.minMsgLen = 1 25 | p.maxMsgLen = 4096 26 | p.littleEndian = false 27 | 28 | return p 29 | } 30 | 31 | // It's dangerous to call the method on reading or writing 32 | func (p *MsgParser) SetMsgLen(lenMsgLen int, minMsgLen uint32, maxMsgLen uint32) { 33 | if lenMsgLen == 1 || lenMsgLen == 2 || lenMsgLen == 4 { 34 | p.lenMsgLen = lenMsgLen 35 | } 36 | if minMsgLen != 0 { 37 | p.minMsgLen = minMsgLen 38 | } 39 | if maxMsgLen != 0 { 40 | p.maxMsgLen = maxMsgLen 41 | } 42 | 43 | var max uint32 44 | switch p.lenMsgLen { 45 | case 1: 46 | max = math.MaxUint8 47 | case 2: 48 | max = math.MaxUint16 49 | case 4: 50 | max = math.MaxUint32 51 | } 52 | if p.minMsgLen > max { 53 | p.minMsgLen = max 54 | } 55 | if p.maxMsgLen > max { 56 | p.maxMsgLen = max 57 | } 58 | } 59 | 60 | // It's dangerous to call the method on reading or writing 61 | func (p *MsgParser) SetByteOrder(littleEndian bool) { 62 | p.littleEndian = littleEndian 63 | } 64 | 65 | // goroutine safe 66 | func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) { 67 | var b [4]byte 68 | bufMsgLen := b[:p.lenMsgLen] 69 | 70 | // read len 71 | if _, err := io.ReadFull(conn, bufMsgLen); err != nil { 72 | return nil, err 73 | } 74 | 75 | // parse len 76 | var msgLen uint32 77 | switch p.lenMsgLen { 78 | case 1: 79 | msgLen = uint32(bufMsgLen[0]) 80 | case 2: 81 | if p.littleEndian { 82 | msgLen = uint32(binary.LittleEndian.Uint16(bufMsgLen)) 83 | } else { 84 | msgLen = uint32(binary.BigEndian.Uint16(bufMsgLen)) 85 | } 86 | case 4: 87 | if p.littleEndian { 88 | msgLen = binary.LittleEndian.Uint32(bufMsgLen) 89 | } else { 90 | msgLen = binary.BigEndian.Uint32(bufMsgLen) 91 | } 92 | } 93 | 94 | // check len 95 | if msgLen > p.maxMsgLen { 96 | return nil, errors.New(fmt.Sprintf("message too long,msgLen=%d,max=%d", msgLen, p.maxMsgLen)) 97 | } else if msgLen < p.minMsgLen { 98 | return nil, errors.New("message too short") 99 | } 100 | 101 | // data 102 | msgData := make([]byte, msgLen) 103 | if _, err := io.ReadFull(conn, msgData); err != nil { 104 | return nil, err 105 | } 106 | fmt.Printf("read msg:%d,%+v", msgLen, msgData) 107 | return msgData, nil 108 | } 109 | 110 | // goroutine safe 111 | func (p *MsgParser) Write(conn *TCPConn, args ...[]byte) error { 112 | // get len 113 | var msgLen uint32 114 | for i := 0; i < len(args); i++ { 115 | msgLen += uint32(len(args[i])) 116 | } 117 | 118 | // check len 119 | if msgLen > p.maxMsgLen { 120 | return errors.New(fmt.Sprintf("message too long,msgLen=%d,max=%d", msgLen, p.maxMsgLen)) 121 | } else if msgLen < p.minMsgLen { 122 | return errors.New("message too short") 123 | } 124 | 125 | msg := make([]byte, uint32(p.lenMsgLen)+msgLen) 126 | 127 | // write len 128 | switch p.lenMsgLen { 129 | case 1: 130 | msg[0] = byte(msgLen) 131 | case 2: 132 | if p.littleEndian { 133 | binary.LittleEndian.PutUint16(msg, uint16(msgLen)) 134 | } else { 135 | binary.BigEndian.PutUint16(msg, uint16(msgLen)) 136 | } 137 | case 4: 138 | if p.littleEndian { 139 | binary.LittleEndian.PutUint32(msg, msgLen) 140 | } else { 141 | binary.BigEndian.PutUint32(msg, msgLen) 142 | } 143 | } 144 | 145 | // write data 146 | l := p.lenMsgLen 147 | for i := 0; i < len(args); i++ { 148 | copy(msg[l:], args[i]) 149 | l += len(args[i]) 150 | } 151 | 152 | conn.Write(msg) 153 | 154 | return nil 155 | } 156 | -------------------------------------------------------------------------------- /data-structures/matrix/matrix.go: -------------------------------------------------------------------------------- 1 | // Package Matrix provides some methods to use with Matrix 2 | package matrix 3 | 4 | import ( 5 | "errors" 6 | ) 7 | 8 | //type Matrix interface { 9 | //CountRows() int 10 | //CountCols() int 11 | //GetElm(i int, j int) float64 12 | //trace() float64 13 | 14 | //SetElm(i int, j int, v float64) 15 | //add(*Matrix) error 16 | //substract(*Matrix) error 17 | //scale(float64) 18 | 19 | //copy() []float64 20 | //diagonalCopy() []float64 21 | //} 22 | 23 | type Matrix struct { 24 | // Number of rows 25 | rows int 26 | // Number of columns 27 | cols int 28 | // Matrix stored as a flat array: Aij = Elements[i*step + j] 29 | Elements []float64 30 | // Offset between rows 31 | step int 32 | } 33 | 34 | func MakeMatrix(Elements []float64, rows, cols int) *Matrix { 35 | A := new(Matrix) 36 | A.rows = rows 37 | A.cols = cols 38 | A.step = cols 39 | A.Elements = Elements 40 | 41 | return A 42 | } 43 | func (A *Matrix) CountRows() int { 44 | return A.rows 45 | } 46 | 47 | func (A *Matrix) CountCols() int { 48 | return A.cols 49 | } 50 | 51 | func (A *Matrix) GetElm(i int, j int) float64 { 52 | return A.Elements[i*A.step+j] 53 | } 54 | 55 | func (A *Matrix) SetElm(i int, j int, v float64) { 56 | A.Elements[i*A.step+j] = v 57 | } 58 | 59 | func (A *Matrix) diagonalCopy() []float64 { 60 | diag := make([]float64, A.cols) 61 | for i := 0; i < len(diag); i++ { 62 | diag[i] = A.GetElm(i, i) 63 | } 64 | return diag 65 | } 66 | 67 | func (A *Matrix) copy() *Matrix { 68 | B := new(Matrix) 69 | B.rows = A.rows 70 | B.cols = A.cols 71 | B.step = A.step 72 | 73 | B.Elements = make([]float64, A.cols*A.rows) 74 | 75 | for i := 0; i < A.rows; i++ { 76 | for j := 0; j < A.cols; j++ { 77 | B.Elements[i*A.step+j] = A.GetElm(i, j) 78 | } 79 | } 80 | return B 81 | } 82 | 83 | func (A *Matrix) trace() float64 { 84 | var tr float64 = 0 85 | for i := 0; i < A.cols; i++ { 86 | tr += A.GetElm(i, i) 87 | } 88 | return tr 89 | } 90 | 91 | func (A *Matrix) add(B *Matrix) error { 92 | if A.cols != B.cols && A.rows != B.rows { 93 | return errors.New("Wrong input sizes") 94 | } 95 | for i := 0; i < A.rows; i++ { 96 | for j := 0; j < A.cols; j++ { 97 | A.SetElm(i, j, A.GetElm(i, j)+B.GetElm(i, j)) 98 | } 99 | } 100 | 101 | return nil 102 | } 103 | 104 | func (A *Matrix) substract(B *Matrix) error { 105 | if A.cols != B.cols && A.rows != B.rows { 106 | return errors.New("Wrong input sizes") 107 | } 108 | for i := 0; i < A.rows; i++ { 109 | for j := 0; j < A.cols; j++ { 110 | A.SetElm(i, j, A.GetElm(i, j)-B.GetElm(i, j)) 111 | } 112 | } 113 | 114 | return nil 115 | } 116 | 117 | func (A *Matrix) scale(a float64) { 118 | for i := 0; i < A.rows; i++ { 119 | for j := 0; j < A.cols; j++ { 120 | A.SetElm(i, j, a*A.GetElm(i, j)) 121 | } 122 | } 123 | } 124 | 125 | func Add(A *Matrix, B *Matrix) *Matrix { 126 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 127 | 128 | for i := 0; i < A.rows; i++ { 129 | for j := 0; j < A.cols; j++ { 130 | result.SetElm(i, j, A.GetElm(i, j)+B.GetElm(i, j)) 131 | } 132 | } 133 | 134 | return result 135 | } 136 | 137 | func Substract(A *Matrix, B *Matrix) *Matrix { 138 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 139 | 140 | for i := 0; i < A.rows; i++ { 141 | for j := 0; j < A.cols; j++ { 142 | result.SetElm(i, j, A.GetElm(i, j)-B.GetElm(i, j)) 143 | } 144 | } 145 | 146 | return result 147 | } 148 | 149 | func Multiply(A *Matrix, B *Matrix) *Matrix { 150 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 151 | 152 | for i := 0; i < A.rows; i++ { 153 | for j := 0; j < A.cols; j++ { 154 | sum := float64(0) 155 | for k := 0; k < A.cols; k++ { 156 | sum += A.GetElm(i, k) * B.GetElm(k, j) 157 | } 158 | result.SetElm(i, j, sum) 159 | } 160 | } 161 | 162 | return result 163 | } 164 | -------------------------------------------------------------------------------- /log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | "os" 8 | "path" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | // levels 14 | const ( 15 | debugLevel = 0 16 | infoLevel = 1 17 | errorLevel = 2 18 | fatalLevel = 3 19 | ) 20 | 21 | const ( 22 | printDebugLevel = "[DEBUG] " 23 | printInfoLevel = "[INFO] " 24 | printErrorLevel = "[ERROR] " 25 | printFatalLevel = "[FATAL] " 26 | ) 27 | 28 | type Logger struct { 29 | level int 30 | baseLogger *log.Logger 31 | baseFile *os.File 32 | } 33 | 34 | func New(strLevel string, pathhead string, pathname string, flag int) (*Logger, error) { 35 | // level 36 | var level int 37 | switch strings.ToLower(strLevel) { 38 | case "debug": 39 | level = debugLevel 40 | case "info": 41 | level = infoLevel 42 | case "error": 43 | level = errorLevel 44 | case "fatal": 45 | level = fatalLevel 46 | default: 47 | return nil, errors.New("unknown level: " + strLevel) 48 | } 49 | 50 | // logger 51 | var baseLogger *log.Logger 52 | var baseFile *os.File 53 | if pathname != "" { 54 | now := time.Now() 55 | 56 | filename := fmt.Sprintf("%v%d%02d%02d.log", pathhead, 57 | now.Year(), 58 | now.Month(), 59 | now.Day()) 60 | 61 | file, err := os.OpenFile(path.Join(pathname, filename), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) //Create(path.Join(pathname, filename)) 62 | if err != nil { 63 | return nil, err 64 | } 65 | 66 | baseLogger = log.New(file, "", flag) 67 | baseFile = file 68 | } else { 69 | baseLogger = log.New(os.Stdout, "", flag) 70 | } 71 | 72 | // new 73 | logger := new(Logger) 74 | logger.level = level 75 | logger.baseLogger = baseLogger 76 | logger.baseFile = baseFile 77 | 78 | return logger, nil 79 | } 80 | 81 | // It's dangerous to call the method on logging 82 | func (logger *Logger) Close() { 83 | if logger.baseFile != nil { 84 | logger.baseFile.Close() 85 | } 86 | 87 | logger.baseLogger = nil 88 | logger.baseFile = nil 89 | } 90 | 91 | func (logger *Logger) doPrintf(level int, printLevel string, format string, a ...interface{}) { 92 | if level < logger.level { 93 | return 94 | } 95 | if logger.baseLogger == nil { 96 | panic("logger closed") 97 | } 98 | 99 | format = printLevel + format 100 | logger.baseLogger.Output(4, fmt.Sprintf(format, a...)) 101 | 102 | if level == fatalLevel { 103 | os.Exit(1) 104 | } 105 | } 106 | 107 | func (logger *Logger) Debug(format string, a ...interface{}) { 108 | logger.doPrintf(debugLevel, printDebugLevel, format, a...) 109 | } 110 | 111 | func (logger *Logger) Info(format string, a ...interface{}) { 112 | logger.doPrintf(infoLevel, printInfoLevel, format, a...) 113 | } 114 | 115 | func (logger *Logger) Error(format string, a ...interface{}) { 116 | logger.doPrintf(errorLevel, printErrorLevel, format, a...) 117 | } 118 | 119 | func (logger *Logger) Fatal(format string, a ...interface{}) { 120 | logger.doPrintf(fatalLevel, printFatalLevel, format, a...) 121 | } 122 | 123 | func (logger *Logger) Println(format string, a ...interface{}) { 124 | logger.Println(format,a...) 125 | } 126 | /* 127 | var gLogger, _ = New("debug", "", "", log.LstdFlags) 128 | 129 | // It's dangerous to call the method on logging 130 | func Export(logger *Logger) { 131 | if logger != nil { 132 | gLogger = logger 133 | } 134 | } 135 | 136 | 137 | func Debug(format string, a ...interface{}) { 138 | gLogger.doPrintf(debugLevel, printDebugLevel, format, a...) 139 | } 140 | 141 | func Info(format string, a ...interface{}) { 142 | gLogger.doPrintf(infoLevel, printInfoLevel, format, a...) 143 | } 144 | 145 | func Println(format string, a ...interface{}) { 146 | str := fmt.Sprint(a) 147 | gLogger.doPrintf(infoLevel, printInfoLevel, format+str) 148 | 149 | } 150 | 151 | func Error(format string, a ...interface{}) { 152 | gLogger.doPrintf(errorLevel, printErrorLevel, format, a...) 153 | } 154 | 155 | func Fatal(format string, a ...interface{}) { 156 | gLogger.doPrintf(fatalLevel, printFatalLevel, format, a...) 157 | } 158 | 159 | func Close() { 160 | gLogger.Close() 161 | } 162 | */ 163 | -------------------------------------------------------------------------------- /network/ws_server.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "github.com/magicsea/ganet/log" 5 | "crypto/tls" 6 | "net" 7 | "net/http" 8 | "sync" 9 | "time" 10 | 11 | "github.com/gorilla/websocket" 12 | ) 13 | 14 | type WSServer struct { 15 | Addr string 16 | MaxConnNum int 17 | PendingWriteNum int 18 | MaxMsgLen uint32 19 | HTTPTimeout time.Duration 20 | CertFile string 21 | KeyFile string 22 | NewAgent func(*WSConn) Agent 23 | ln net.Listener 24 | handler *WSHandler 25 | } 26 | 27 | type WSHandler struct { 28 | maxConnNum int 29 | pendingWriteNum int 30 | maxMsgLen uint32 31 | newAgent func(*WSConn) Agent 32 | upgrader websocket.Upgrader 33 | conns WebsocketConnSet 34 | mutexConns sync.Mutex 35 | wg sync.WaitGroup 36 | } 37 | 38 | func (handler *WSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 39 | if r.Method != "GET" { 40 | http.Error(w, "Method not allowed", 405) 41 | return 42 | } 43 | conn, err := handler.upgrader.Upgrade(w, r, nil) 44 | if err != nil { 45 | log.Debug("upgrade error: %v", err) 46 | return 47 | } 48 | conn.SetReadLimit(int64(handler.maxMsgLen)) 49 | 50 | handler.wg.Add(1) 51 | defer handler.wg.Done() 52 | 53 | handler.mutexConns.Lock() 54 | if handler.conns == nil { 55 | handler.mutexConns.Unlock() 56 | conn.Close() 57 | return 58 | } 59 | if len(handler.conns) >= handler.maxConnNum { 60 | handler.mutexConns.Unlock() 61 | conn.Close() 62 | log.Debug("too many connections") 63 | return 64 | } 65 | handler.conns[conn] = struct{}{} 66 | handler.mutexConns.Unlock() 67 | 68 | wsConn := newWSConn(conn, handler.pendingWriteNum, handler.maxMsgLen) 69 | agent := handler.newAgent(wsConn) 70 | agent.Run() 71 | 72 | // cleanup 73 | wsConn.Close() 74 | handler.mutexConns.Lock() 75 | delete(handler.conns, conn) 76 | handler.mutexConns.Unlock() 77 | agent.OnClose() 78 | } 79 | 80 | func (server *WSServer) Start() { 81 | ln, err := net.Listen("tcp", server.Addr) 82 | if err != nil { 83 | log.Fatal("%v", err) 84 | } 85 | 86 | if server.MaxConnNum <= 0 { 87 | server.MaxConnNum = 100 88 | log.Info("invalid MaxConnNum, reset to %v", server.MaxConnNum) 89 | } 90 | if server.PendingWriteNum <= 0 { 91 | server.PendingWriteNum = 100 92 | log.Info("invalid PendingWriteNum, reset to %v", server.PendingWriteNum) 93 | } 94 | if server.MaxMsgLen <= 0 { 95 | server.MaxMsgLen = 4096 96 | log.Info("invalid MaxMsgLen, reset to %v", server.MaxMsgLen) 97 | } 98 | if server.HTTPTimeout <= 0 { 99 | server.HTTPTimeout = 10 * time.Second 100 | log.Info("invalid HTTPTimeout, reset to %v", server.HTTPTimeout) 101 | } 102 | if server.NewAgent == nil { 103 | log.Fatal("NewAgent must not be nil") 104 | } 105 | 106 | if server.CertFile != "" || server.KeyFile != "" { 107 | config := &tls.Config{} 108 | config.NextProtos = []string{"http/1.1"} 109 | 110 | var err error 111 | config.Certificates = make([]tls.Certificate, 1) 112 | config.Certificates[0], err = tls.LoadX509KeyPair(server.CertFile, server.KeyFile) 113 | if err != nil { 114 | log.Fatal("%v", err) 115 | } 116 | 117 | ln = tls.NewListener(ln, config) 118 | } 119 | 120 | server.ln = ln 121 | server.handler = &WSHandler{ 122 | maxConnNum: server.MaxConnNum, 123 | pendingWriteNum: server.PendingWriteNum, 124 | maxMsgLen: server.MaxMsgLen, 125 | newAgent: server.NewAgent, 126 | conns: make(WebsocketConnSet), 127 | upgrader: websocket.Upgrader{ 128 | HandshakeTimeout: server.HTTPTimeout, 129 | CheckOrigin: func(_ *http.Request) bool { return true }, 130 | }, 131 | } 132 | 133 | httpServer := &http.Server{ 134 | Addr: server.Addr, 135 | Handler: server.handler, 136 | ReadTimeout: server.HTTPTimeout, 137 | WriteTimeout: server.HTTPTimeout, 138 | MaxHeaderBytes: 1024, 139 | } 140 | 141 | go httpServer.Serve(ln) 142 | } 143 | 144 | func (server *WSServer) Close() { 145 | server.ln.Close() 146 | 147 | server.handler.mutexConns.Lock() 148 | for conn := range server.handler.conns { 149 | conn.Close() 150 | } 151 | server.handler.conns = nil 152 | server.handler.mutexConns.Unlock() 153 | 154 | server.handler.wg.Wait() 155 | } 156 | -------------------------------------------------------------------------------- /util/math.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "math" 5 | "math/rand" 6 | ) 7 | 8 | func Abs(i int) int { 9 | if i < 0 { 10 | return -i 11 | } 12 | return i 13 | } 14 | 15 | func Abs32(i int32) int32 { 16 | if i < 0 { 17 | return -i 18 | } 19 | return i 20 | } 21 | 22 | func IMax(a, b int) int { 23 | if a > b { 24 | return a 25 | } 26 | return b 27 | } 28 | func I32Max(a, b int32) int32 { 29 | if a > b { 30 | return a 31 | } 32 | return b 33 | } 34 | func I64Max(a, b int64) int64 { 35 | if a > b { 36 | return a 37 | } 38 | return b 39 | } 40 | 41 | func IMin(a, b int) int { 42 | if a < b { 43 | return a 44 | } 45 | return b 46 | } 47 | func I32Min(a, b int32) int32 { 48 | if a < b { 49 | return a 50 | } 51 | return b 52 | } 53 | func I64Min(a, b int64) int64 { 54 | if a < b { 55 | return a 56 | } 57 | return b 58 | } 59 | 60 | //取中间值 61 | func IClamp(value, min, max int) int { 62 | if value < min { 63 | value = min 64 | } 65 | if value > max { 66 | value = max 67 | } 68 | return value 69 | } 70 | 71 | //取中间值 72 | func I32Clamp(value, min, max int32) int32 { 73 | if value < min { 74 | value = min 75 | } 76 | if value > max { 77 | value = max 78 | } 79 | return value 80 | } 81 | 82 | //取中间值 83 | func I64Clamp(value, min, max int64) int64 { 84 | if value < min { 85 | value = min 86 | } 87 | if value > max { 88 | value = max 89 | } 90 | return value 91 | } 92 | 93 | //随机范围[from, to] 94 | func RandRange(from, to int) int { 95 | return rand.Intn(to-from+1) + from 96 | } 97 | func RandRange32(from, to int32) int32 { 98 | var i = rand.Intn(int(to)-int(from)+1) + int(from) 99 | return int32(i) 100 | } 101 | 102 | //随机乱序,洗牌 103 | func Shuffle(list []interface{}) { 104 | var c = len(list) 105 | if c < 2 { 106 | return 107 | } 108 | 109 | for i := 0; i < c-1; i++ { 110 | var j = rand.Intn(c-i) + i //这里rand需要包含i自身,否则不均匀 111 | if i != j { 112 | list[i], list[j] = list[j], list[i] 113 | } 114 | } 115 | } 116 | 117 | //随机抽取n张 118 | func ShuffleN(list []interface{}, randCount int) []interface{} { 119 | var c = len(list) 120 | if c < 2 { 121 | return list 122 | } 123 | 124 | var ct = IMin(c-1, randCount) 125 | for i := 0; i < ct; i++ { 126 | var j = rand.Intn(c-i) + i //这里rand需要包含i自身,否则不均匀 127 | if i != j { 128 | list[i], list[j] = list[j], list[i] 129 | } 130 | } 131 | 132 | return list[:ct] 133 | } 134 | 135 | func ShuffleI32(list []int32) { 136 | var c = len(list) 137 | if c < 2 { 138 | return 139 | } 140 | 141 | for i := 0; i < c-1; i++ { 142 | var j = rand.Intn(c-i) + i //这里rand需要包含i自身,否则不均匀 143 | if i != j { 144 | list[i], list[j] = list[j], list[i] 145 | } 146 | } 147 | } 148 | 149 | func ShuffleNI32(list []int32, randCount int) []int32 { 150 | var c = len(list) 151 | if c < 2 { 152 | return list 153 | } 154 | 155 | var ct = IMin(c-1, randCount) 156 | for i := 0; i < ct; i++ { 157 | var j = rand.Intn(c-i) + i //这里rand需要包含i自身,否则不均匀 158 | if i != j { 159 | list[i], list[j] = list[j], list[i] 160 | } 161 | } 162 | return list[:ct] 163 | } 164 | 165 | func ShuffleI(list []int) { 166 | var c = len(list) 167 | if c < 2 { 168 | return 169 | } 170 | 171 | for i := 0; i < c-1; i++ { 172 | var j = rand.Intn(c-i) + i //这里rand需要包含i自身,否则不均匀 173 | if i != j { 174 | list[i], list[j] = list[j], list[i] 175 | } 176 | } 177 | } 178 | 179 | //随机乱序,洗牌,反向,效果一样 180 | func ShuffleR(list []interface{}) { 181 | var c = len(list) 182 | if c < 2 { 183 | return 184 | } 185 | 186 | for i := c - 1; i >= 1; i-- { 187 | var j = rand.Int() % (i + 1) 188 | list[i], list[j] = list[j], list[i] 189 | } 190 | } 191 | 192 | //数组求和 193 | func SumI32(list []int32) int32 { 194 | var sum int32 195 | for _, v := range list { 196 | sum += v 197 | } 198 | return sum 199 | } 200 | 201 | //矩阵列求和 202 | func SumMatrixColI32(mat [][]int32, col int) int32 { 203 | var list []int32 204 | for index := 0; index < len(mat); index++ { 205 | list = append(list, mat[index][col]) 206 | } 207 | return SumI32(list) 208 | } 209 | 210 | //固定种子伪随机 211 | func StaticRand(seedrare, min, max int) int { 212 | var seed = float64(seedrare) 213 | seed = seed*2045 + 1 214 | seed = float64(int(seed) % 1048576) 215 | var dis = float64(max - min) 216 | var ret = int(min) + int(math.Floor(seed)*dis/1048576) 217 | return ret 218 | } 219 | -------------------------------------------------------------------------------- /data-structures/graph/graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | type VertexId uint 8 | 9 | type Vertices []VertexId 10 | 11 | type Edge struct { 12 | From VertexId 13 | To VertexId 14 | } 15 | 16 | type graph struct { 17 | edges map[VertexId]map[VertexId]int 18 | edgesCount int 19 | isDirected bool 20 | } 21 | 22 | type EdgesIterable interface { 23 | EdgesIter() <-chan Edge 24 | } 25 | 26 | type VerticesIterable interface { 27 | VerticesIter() <-chan VertexId 28 | } 29 | 30 | func (g *graph) EdgesIter() <-chan Edge { 31 | ch := make(chan Edge) 32 | go func() { 33 | for from, connectedVertices := range g.edges { 34 | for to, _ := range connectedVertices { 35 | if g.isDirected { 36 | ch <- Edge{from, to} 37 | } else { 38 | if from < to { 39 | ch <- Edge{from, to} 40 | } 41 | } 42 | } 43 | } 44 | close(ch) 45 | }() 46 | return ch 47 | } 48 | 49 | func (g *graph) VerticesIter() <-chan VertexId { 50 | ch := make(chan VertexId) 51 | go func() { 52 | for vertex, _ := range g.edges { 53 | ch <- vertex 54 | } 55 | close(ch) 56 | }() 57 | return ch 58 | } 59 | 60 | func (g *graph) CheckVertex(vertex VertexId) bool { 61 | _, exists := g.edges[vertex] 62 | 63 | return exists 64 | } 65 | 66 | func (g *graph) TouchVertex(vertex VertexId) { 67 | if _, ok := g.edges[vertex]; !ok { 68 | g.edges[vertex] = make(map[VertexId]int) 69 | } 70 | } 71 | 72 | func (g *graph) AddVertex(vertex VertexId) error { 73 | i, _ := g.edges[vertex] 74 | if i != nil { 75 | return errors.New("Vertex already exists") 76 | } 77 | 78 | g.edges[vertex] = make(map[VertexId]int) 79 | 80 | return nil 81 | } 82 | 83 | func (g *graph) RemoveVertex(vertex VertexId) error { 84 | if !g.IsVertex(vertex) { 85 | return errors.New("Unknown vertex") 86 | } 87 | 88 | delete(g.edges, vertex) 89 | 90 | for _, connectedVertices := range g.edges { 91 | delete(connectedVertices, vertex) 92 | } 93 | 94 | return nil 95 | } 96 | 97 | func (g *graph) IsVertex(vertex VertexId) (exist bool) { 98 | _, exist = g.edges[vertex] 99 | 100 | return 101 | } 102 | 103 | func (g *graph) VerticesCount() int { 104 | return len(g.edges) 105 | } 106 | 107 | func (g *graph) AddEdge(from, to VertexId, weight int) error { 108 | if from == to { 109 | return errors.New("Cannot add self loop") 110 | } 111 | 112 | if !g.CheckVertex(from) || !g.CheckVertex(to) { 113 | return errors.New("Vertices don't exist") 114 | } 115 | 116 | i, _ := g.edges[from][to] 117 | j, _ := g.edges[to][from] 118 | 119 | if i > 0 || j > 0 { 120 | return errors.New("Edge already defined") 121 | } 122 | 123 | g.TouchVertex(from) 124 | g.TouchVertex(to) 125 | 126 | g.edges[from][to] = weight 127 | 128 | if !g.isDirected { 129 | g.edges[to][from] = weight 130 | } 131 | 132 | g.edgesCount++ 133 | 134 | return nil 135 | } 136 | 137 | func (g *graph) RemoveEdge(from, to VertexId) error { 138 | i, _ := g.edges[from][to] 139 | j, _ := g.edges[to][from] 140 | 141 | if i == -1 || j == -1 { 142 | return errors.New("Edge doesn't exist") 143 | } 144 | 145 | g.edges[from][to] = -1 146 | 147 | if !g.isDirected { 148 | g.edges[to][from] = -1 149 | } 150 | 151 | g.edgesCount-- 152 | 153 | return nil 154 | } 155 | 156 | func (g *graph) IsEdge(from, to VertexId) bool { 157 | connected, ok := g.edges[from] 158 | 159 | if !ok { 160 | return false 161 | } 162 | 163 | weight := connected[to] 164 | return weight > 0 165 | } 166 | 167 | func (g *graph) Order() int { 168 | return len(g.edges) 169 | } 170 | 171 | func (g *graph) EdgesCount() int { 172 | return g.edgesCount 173 | } 174 | 175 | func (g *graph) GetEdge(from, to VertexId) int { 176 | return g.edges[from][to] 177 | } 178 | 179 | func (g *graph) GetNeighbours(vertex VertexId) VerticesIterable { 180 | iterator := func() <-chan VertexId { 181 | ch := make(chan VertexId) 182 | go func() { 183 | if connected, ok := g.edges[vertex]; ok { 184 | for VertexId, _ := range connected { 185 | ch <- VertexId 186 | } 187 | } 188 | close(ch) 189 | }() 190 | return ch 191 | } 192 | 193 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 194 | } 195 | 196 | type vertexIterableHelper struct { 197 | iterFunc func() <-chan VertexId 198 | } 199 | 200 | func (helper *vertexIterableHelper) VerticesIter() <-chan VertexId { 201 | return helper.iterFunc() 202 | } 203 | -------------------------------------------------------------------------------- /data-structures/list/list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //not safe list 8 | type List struct { 9 | data []interface{} 10 | } 11 | 12 | func New(data ...interface{}) *List { 13 | l := &List{} 14 | l.Append(data...) 15 | return l 16 | } 17 | 18 | //添加一个 19 | func (l *List) Add(v interface{}) { 20 | l.data = append(l.data, v) 21 | } 22 | 23 | //附加一组 24 | func (l *List) Append(v ...interface{}) { 25 | l.data = append(l.data, v...) 26 | } 27 | 28 | //数量 29 | func (l *List) Count() int { 30 | return len(l.data) 31 | } 32 | 33 | //插入 34 | func (l *List) Insert(index int, o interface{}) int { 35 | 36 | if index > len(l.data) { 37 | index = len(l.data) 38 | } 39 | if index < 0 { 40 | index = 0 41 | } 42 | var R []interface{} 43 | R = append(R, l.data[index:]...) 44 | l.data = append(l.data[:index], o) 45 | l.data = append(l.data, R...) 46 | return index 47 | } 48 | 49 | //合并 50 | func (l *List) Concat(k *List) { 51 | l.data = append(l.data, k.RawList()...) 52 | } 53 | 54 | //深拷贝 55 | func (l *List) DeepCopy(k *List) { 56 | l.data = append(l.data[0:0], k.RawList()...) 57 | } 58 | 59 | //按序号移除一个节点 60 | func (l *List) Remove(index int) interface{} { 61 | if index < 0 || index >= len(l.data) { 62 | return nil 63 | } 64 | v := l.data[index] 65 | l.data = append(l.data[:index], l.data[index+1:]...) 66 | return v 67 | } 68 | 69 | type RuleFunc func(interface{}) bool 70 | 71 | //移除一个相等的单位,返回索引,失败返回false 72 | func (l *List) RemoveEquel(o interface{}) bool { 73 | for index := 0; index < len(l.data); index++ { 74 | v := l.data[index] 75 | if v == o { 76 | l.data = append(l.data[:index], l.data[index+1:]...) 77 | return true 78 | } 79 | } 80 | return false 81 | } 82 | 83 | //移除一个节点 84 | func (l *List) RemoveRule(rule RuleFunc) interface{} { 85 | for index := 0; index < len(l.data); index++ { 86 | v := l.data[index] 87 | if rule(v) { 88 | l.data = append(l.data[:index], l.data[index+1:]...) 89 | return v 90 | } 91 | } 92 | return nil 93 | } 94 | 95 | //移除所有符合条件节点 96 | func (l *List) RemoveAllRule(rule RuleFunc) int { 97 | var i, c int 98 | le := len(l.data) 99 | for { 100 | if i+c >= le { 101 | break 102 | } 103 | v := l.data[i] 104 | if rule(v) { 105 | l.data = append(l.data[:i], l.data[i+1:]...) 106 | c++ 107 | } else { 108 | i++ 109 | } 110 | } 111 | 112 | return c 113 | } 114 | 115 | //所有节点执行f函数 116 | func (l *List) Each(f func(o interface{})) { 117 | for _, v := range l.data { 118 | f(v) 119 | } 120 | } 121 | 122 | func (l *List) EachElse(f func(o interface{}) bool) bool { 123 | var isbreak = false 124 | for _, v := range l.data { 125 | if f(v) { 126 | isbreak = true 127 | break 128 | } 129 | } 130 | return isbreak 131 | } 132 | 133 | //匹配函数 134 | func (l *List) MatchPair(f func(o1, o2 interface{}) bool) (bool, interface{}, interface{}) { 135 | if l.Count() < 2 { 136 | return false, nil, nil 137 | } 138 | for _, v := range l.data { 139 | for _, v2 := range l.data { 140 | if v != v2 && f(v, v2) { 141 | return true, v, v2 142 | } 143 | } 144 | } 145 | return false, nil, nil 146 | } 147 | 148 | type PairInterface struct { 149 | I1 interface{} 150 | I2 interface{} 151 | } 152 | 153 | func findPairInterface(plist []PairInterface, o interface{}) bool { 154 | for _, p := range plist { 155 | if p.I1 == o || p.I2 == o { 156 | return true 157 | } 158 | } 159 | return false 160 | } 161 | 162 | //匹配函数 一次遍历,会将移除的 163 | func (list *List) MatchPairList(f func(o1, o2 interface{}) bool) []PairInterface { 164 | if list.Count() < 2 { 165 | return nil 166 | } 167 | 168 | var plist []PairInterface 169 | //成功的设置nil 170 | for _, node := range list.data { 171 | for _, node2 := range list.data { 172 | if node != nil && node2 != nil && node != node2 { 173 | f1 := findPairInterface(plist, node) 174 | f2 := findPairInterface(plist, node2) 175 | if !f1 && !f2 && f(node, node2) { 176 | p := PairInterface{node, node2} 177 | plist = append(plist, p) 178 | fmt.Println("mathc:", p) 179 | } 180 | } 181 | } 182 | } 183 | //清空空位 184 | // if len(plist) > 0 { 185 | // for _, v := range plist { 186 | // list.RemoveEquel(v.I1) 187 | // list.RemoveEquel(v.I2) 188 | // fmt.Println("rem:", v) 189 | // } 190 | // } 191 | 192 | return plist 193 | } 194 | 195 | //按规则查找一个 196 | func (l *List) Find(rule RuleFunc) interface{} { 197 | for _, v := range l.data { 198 | if rule(v) { 199 | return v 200 | } 201 | } 202 | return nil 203 | } 204 | 205 | //按规则查找所有 206 | func (l *List) FindAll(rule RuleFunc) []interface{} { 207 | var tempL []interface{} 208 | for _, v := range l.data { 209 | if rule(v) { 210 | tempL = append(tempL, v) 211 | } 212 | } 213 | return tempL 214 | } 215 | 216 | //原始列表 217 | func (l *List) RawList() []interface{} { 218 | return l.data 219 | } 220 | 221 | //清理 222 | func (l *List) Clear() { 223 | l.data = nil 224 | } 225 | 226 | func (l *List) String() string { 227 | return fmt.Sprintf("%v", l.data) 228 | } 229 | -------------------------------------------------------------------------------- /mysqldb/dbclient_test.go: -------------------------------------------------------------------------------- 1 | package mysqldb 2 | 3 | import ( 4 | "testing" 5 | 6 | "fmt" 7 | 8 | "github.com/astaxie/beego/orm" 9 | ) 10 | 11 | type User struct { 12 | Id int 13 | Name string 14 | Profile *Profile `orm:"rel(one)"` // OneToOne relation 15 | Post []*Post `orm:"reverse(many)"` // 设置一对多的反向关系 16 | } 17 | 18 | type Profile struct { 19 | Id int 20 | Age int16 21 | User *User `orm:"reverse(one)"` // 设置一对一反向关系(可选) 22 | } 23 | 24 | type Post struct { 25 | Id int 26 | Title string 27 | User *User `orm:"rel(fk)"` //设置一对多关系 28 | Tags []*Tag `orm:"rel(m2m)"` 29 | } 30 | 31 | type Tag struct { 32 | Id int 33 | Name string 34 | Posts []*Post `orm:"reverse(many)"` 35 | } 36 | 37 | //主键`orm:"pk"` 38 | //唯一`orm:"unique"` 39 | //忽略`orm:"-"` 40 | //允许空`orm:"null"` 41 | //varchar大小`orm:"size(60)" 42 | //默认`orm:"default(1)"` 43 | type Player struct { 44 | Id int `orm:"column(uid)",auto` 45 | Name string `orm:"column(username)"` 46 | Cgid int 47 | Lv int 48 | Exp int 49 | Exptime int64 50 | } 51 | 52 | func TestDB_rui_normal(t *testing.T) { 53 | orm.RegisterModel(new(Player)) 54 | //连接数据库 55 | client, err := ConnectDB("root:tcg123456@tcp(192.168.3.194:3306)/tcg_new", "default") 56 | if err != nil { 57 | t.Error(err) 58 | return 59 | } 60 | //增加记录 61 | /* 62 | sql := fmt.Sprintf("insert into player values(1, ?, 2, 3, 4, 342423423)") 63 | _, err1 := client.Raw(sql, []string{"a"}).Exec() 64 | if err1 != nil { 65 | t.Error(err1) 66 | return 67 | } 68 | for i := 2; i <= 10; i++ { 69 | sql = fmt.Sprintf("insert into player values(?, \"ufo\", 2, ?, 4, 342423423)") 70 | _, err1 = client.Raw(sql, []int{i, i + 1}).Exec() 71 | if err1 != nil { 72 | t.Error(err1) 73 | return 74 | } 75 | } 76 | */ 77 | //查询 78 | 79 | p := new(Player) 80 | sql1 := fmt.Sprintf("select * from player where uid = ?") 81 | err = client.Raw(sql1, []int{1}).QueryRow(&p) 82 | if err != nil { 83 | t.Error(err) 84 | } 85 | fmt.Printf("select uid:%d, name :%s, Cgid :%d, \nlv :%d, exp :%d, exptime:%u", p.Id, p.Name, p.Cgid, p.Lv, p.Exp, p.Exptime) 86 | fmt.Printf("\nplayer uid is 1 %v\n", p) 87 | ps := make([]Player, 6) 88 | //var Player []ps 89 | sql1 = fmt.Sprintf("select * from player where uid >= ?") 90 | num, errr := client.Raw(sql1, 5).QueryRows(&ps) 91 | if errr != nil { 92 | t.Error(errr) 93 | return 94 | } else { 95 | fmt.Printf("共查询到 %d 个玩家\n", num) 96 | for index, _ := range ps { 97 | fmt.Printf("\n第 %d 玩家信息为:%v", index+1, ps[index]) 98 | } 99 | fmt.Printf("\n") 100 | } 101 | 102 | //删除某些记录 103 | /* 104 | sql = fmt.Sprintf("delete from player WHERE uid = ?;") 105 | fmt.Println(sql) 106 | _, err3 := client.Raw(sql, []int{1}).Exec() 107 | if err3 != nil { 108 | t.Error(err3) 109 | return 110 | } 111 | */ 112 | //修改记录 113 | sqlUpdate := fmt.Sprintf("update player set lv = ?") 114 | _, err = client.Raw(sqlUpdate, []int{111}).Exec() 115 | if err != nil { 116 | t.Error(err) 117 | return 118 | } 119 | 120 | } 121 | 122 | func TestDB_ruiy(t *testing.T) { 123 | //数据库 表注册 124 | orm.RegisterModel(new(Player)) 125 | //连接数据库 126 | client, err := ConnectDB("root:tcg123456@tcp(192.168.3.194:3306)/tcg_new", "default") 127 | if err != nil { 128 | t.Error(err) 129 | return 130 | } 131 | p0 := new(Player) 132 | client.Delete(p0) 133 | //增加记录 134 | /* 135 | var p1 *Player = &Player{Id: 1, Name: "a", Cgid: 1, Lv: 2, Exp: 12, Exptime: time.Now().Unix()} 136 | var p2 *Player = &Player{Id: 2, Name: "b", Cgid: 2, Lv: 3, Exp: 13, Exptime: time.Now().Unix()} 137 | //插入数据 138 | fmt.Println(client.Insert(p1)) 139 | fmt.Println(client.Insert(p2)) 140 | players := []Player{ 141 | {Id: 3, Name: "c", Cgid: 3, Lv: 4, Exp: 14, Exptime: time.Now().Unix()}, 142 | {Id: 4, Name: "d", Cgid: 4, Lv: 5, Exp: 15, Exptime: time.Now().Unix()}, 143 | {Id: 5, Name: "e", Cgid: 5, Lv: 6, Exp: 16, Exptime: time.Now().Unix()}, 144 | } 145 | //批量插入 146 | client.InsertMulti(3, players) 147 | */ 148 | //删除记录 149 | /* 150 | p3 := new(Player) 151 | p3.Id = 4 152 | client.Delete(p3) 153 | */ 154 | 155 | //修改记录 156 | /* 157 | player1 := new(Player) 158 | player1.Id = 2 159 | player1.Name = "change name" 160 | client.Update(player1, "Name") 161 | err2 := client.Read(player1) 162 | if err2 != nil { 163 | t.Error(err2) 164 | return 165 | } 166 | fmt.Println("\n update end select is :", player1) 167 | */ 168 | //查询记录 169 | /* 170 | player := new(Player) 171 | player.Id = 1 172 | err1 := client.Read(player) 173 | if err1 != nil { 174 | t.Error(err1) 175 | return 176 | } 177 | fmt.Println("\nselect data is :", player) 178 | */ 179 | 180 | } 181 | 182 | func TestDB(t *testing.T) { 183 | orm.RegisterModel(new(Player)) 184 | client, err := ConnectDB("root:tcg123456@tcp(192.168.3.194:3306)/test", "default") 185 | if err != nil { 186 | t.Error(err) 187 | return 188 | } 189 | p := Player{Id: 6000, Name: "www", Exp: 1} 190 | client.Insert(&p) 191 | if err := client.Read(&p, "Exp"); err != nil { 192 | t.Error(err) 193 | return 194 | } 195 | p.Name = "yyyy" 196 | client.Update(&p, "Name") 197 | //client.Delete(&p, "Exp") 198 | t.Log("insert ok :", p) 199 | } 200 | 201 | func Test1(t *testing.T) { 202 | /* 203 | data := "[600003, 510000, 520000, 709999]" 204 | if len(data) > 0 { 205 | t := strings.Split(data, "[") 206 | te := strings.Split(t[1], "]") 207 | tem := strings.Split(te[0], ",") 208 | temp := map[int64]int8{} 209 | for k, v := range tem { 210 | var id int64 211 | if k == 0 { 212 | id = int64(GDataManager.String2Int32(v)) 213 | } else { 214 | id = int64(GDataManager.String2Int32(v[1:])) 215 | } 216 | temp[id] = 1 217 | } 218 | fmt.Printf("_________a___:%v\n", tem) 219 | fmt.Printf("_________b___:%v \n", temp) 220 | } 221 | */ 222 | /* 223 | fmt.Printf("now time is :%v\n", time.Now().Unix()) 224 | local := "[12354, 45006,503200]" 225 | tt := strings.Split(local, "[") 226 | te := strings.Split(tt[1], "]") 227 | tem := strings.Split(te[0], ",") 228 | fmt.Printf("data is :%v\n\n", tem) 229 | for _, v := range tem { 230 | //result, _ := strconv.Atoi(v) 231 | //fmt.Printf("test data is :%s\n", v) 232 | //fmt.Printf("test string2int :%d\n\n", result) 233 | r := []rune(v) 234 | onelocal := "" 235 | for i := 0; i < len(r); i++ { 236 | cc, _ := strconv.Atoi(string(r[i])) 237 | if cc > 0 || (cc == 0 && i > 0) { 238 | onelocal = onelocal + string(r[i]) 239 | } 240 | } 241 | ccc, _ := strconv.Atoi(onelocal) 242 | fmt.Printf("\nwang get :%d\n", ccc) 243 | } 244 | */ 245 | 246 | } 247 | 248 | /* 249 | func main() { 250 | o := orm.NewOrm() 251 | o.Using("default") // 默认使用 default,你可以指定为其他数据库 252 | 253 | profile := new(Profile) 254 | profile.Age = 30 255 | 256 | user := new(User) 257 | user.Profile = profile 258 | user.Name = "slene" 259 | 260 | fmt.Println(o.Insert(profile)) 261 | fmt.Println(o.Insert(user)) 262 | 263 | } 264 | */ 265 | -------------------------------------------------------------------------------- /util/uuid.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2015 by Maxim Bublis 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining 4 | // a copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to 8 | // permit persons to whom the Software is furnished to do so, subject to 9 | // the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be 12 | // included in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | // Package uuid provides implementation of Universally Unique Identifier (UUID). 23 | // Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and 24 | // version 2 (as specified in DCE 1.1). 25 | package util 26 | 27 | import ( 28 | "bytes" 29 | "crypto/md5" 30 | "crypto/rand" 31 | "crypto/sha1" 32 | "database/sql/driver" 33 | "encoding/binary" 34 | "encoding/hex" 35 | "fmt" 36 | "hash" 37 | "net" 38 | "os" 39 | "sync" 40 | "time" 41 | ) 42 | 43 | // UUID layout variants. 44 | const ( 45 | VariantNCS = iota 46 | VariantRFC4122 47 | VariantMicrosoft 48 | VariantFuture 49 | ) 50 | 51 | // UUID DCE domains. 52 | const ( 53 | DomainPerson = iota 54 | DomainGroup 55 | DomainOrg 56 | ) 57 | 58 | // Difference in 100-nanosecond intervals between 59 | // UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). 60 | const epochStart = 122192928000000000 61 | 62 | // Used in string method conversion 63 | const dash byte = '-' 64 | 65 | // UUID v1/v2 storage. 66 | var ( 67 | storageMutex sync.Mutex 68 | storageOnce sync.Once 69 | epochFunc = unixTimeFunc 70 | clockSequence uint16 71 | lastTime uint64 72 | hardwareAddr [6]byte 73 | posixUID = uint32(os.Getuid()) 74 | posixGID = uint32(os.Getgid()) 75 | ) 76 | 77 | // String parse helpers. 78 | var ( 79 | urnPrefix = []byte("urn:uuid:") 80 | byteGroups = []int{8, 4, 4, 4, 12} 81 | ) 82 | 83 | func initClockSequence() { 84 | buf := make([]byte, 2) 85 | safeRandom(buf) 86 | clockSequence = binary.BigEndian.Uint16(buf) 87 | } 88 | 89 | func initHardwareAddr() { 90 | interfaces, err := net.Interfaces() 91 | if err == nil { 92 | for _, iface := range interfaces { 93 | if len(iface.HardwareAddr) >= 6 { 94 | copy(hardwareAddr[:], iface.HardwareAddr) 95 | return 96 | } 97 | } 98 | } 99 | 100 | // Initialize hardwareAddr randomly in case 101 | // of real network interfaces absence 102 | safeRandom(hardwareAddr[:]) 103 | 104 | // Set multicast bit as recommended in RFC 4122 105 | hardwareAddr[0] |= 0x01 106 | } 107 | 108 | func initStorage() { 109 | initClockSequence() 110 | initHardwareAddr() 111 | } 112 | 113 | func safeRandom(dest []byte) { 114 | if _, err := rand.Read(dest); err != nil { 115 | panic(err) 116 | } 117 | } 118 | 119 | // Returns difference in 100-nanosecond intervals between 120 | // UUID epoch (October 15, 1582) and current time. 121 | // This is default epoch calculation function. 122 | func unixTimeFunc() uint64 { 123 | return epochStart + uint64(time.Now().UnixNano()/100) 124 | } 125 | 126 | // UUID representation compliant with specification 127 | // described in RFC 4122. 128 | type UUID [16]byte 129 | 130 | // NullUUID can be used with the standard sql package to represent a 131 | // UUID value that can be NULL in the database 132 | type NullUUID struct { 133 | UUID UUID 134 | Valid bool 135 | } 136 | 137 | // The nil UUID is special form of UUID that is specified to have all 138 | // 128 bits set to zero. 139 | var Nil = UUID{} 140 | 141 | // Predefined namespace UUIDs. 142 | var ( 143 | NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 144 | NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8") 145 | NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8") 146 | NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8") 147 | ) 148 | 149 | // And returns result of binary AND of two UUIDs. 150 | func And(u1 UUID, u2 UUID) UUID { 151 | u := UUID{} 152 | for i := 0; i < 16; i++ { 153 | u[i] = u1[i] & u2[i] 154 | } 155 | return u 156 | } 157 | 158 | // Or returns result of binary OR of two UUIDs. 159 | func Or(u1 UUID, u2 UUID) UUID { 160 | u := UUID{} 161 | for i := 0; i < 16; i++ { 162 | u[i] = u1[i] | u2[i] 163 | } 164 | return u 165 | } 166 | 167 | // Equal returns true if u1 and u2 equals, otherwise returns false. 168 | func Equal(u1 UUID, u2 UUID) bool { 169 | return bytes.Equal(u1[:], u2[:]) 170 | } 171 | 172 | // Version returns algorithm version used to generate UUID. 173 | func (u UUID) Version() uint { 174 | return uint(u[6] >> 4) 175 | } 176 | 177 | // Variant returns UUID layout variant. 178 | func (u UUID) Variant() uint { 179 | switch { 180 | case (u[8] & 0x80) == 0x00: 181 | return VariantNCS 182 | case (u[8]&0xc0)|0x80 == 0x80: 183 | return VariantRFC4122 184 | case (u[8]&0xe0)|0xc0 == 0xc0: 185 | return VariantMicrosoft 186 | } 187 | return VariantFuture 188 | } 189 | 190 | // Bytes returns bytes slice representation of UUID. 191 | func (u UUID) Bytes() []byte { 192 | return u[:] 193 | } 194 | 195 | // Returns canonical string representation of UUID: 196 | // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. 197 | func (u UUID) String() string { 198 | buf := make([]byte, 36) 199 | 200 | hex.Encode(buf[0:8], u[0:4]) 201 | buf[8] = dash 202 | hex.Encode(buf[9:13], u[4:6]) 203 | buf[13] = dash 204 | hex.Encode(buf[14:18], u[6:8]) 205 | buf[18] = dash 206 | hex.Encode(buf[19:23], u[8:10]) 207 | buf[23] = dash 208 | hex.Encode(buf[24:], u[10:]) 209 | 210 | return string(buf) 211 | } 212 | 213 | // SetVersion sets version bits. 214 | func (u *UUID) SetVersion(v byte) { 215 | u[6] = (u[6] & 0x0f) | (v << 4) 216 | } 217 | 218 | // SetVariant sets variant bits as described in RFC 4122. 219 | func (u *UUID) SetVariant() { 220 | u[8] = (u[8] & 0xbf) | 0x80 221 | } 222 | 223 | // MarshalText implements the encoding.TextMarshaler interface. 224 | // The encoding is the same as returned by String. 225 | func (u UUID) MarshalText() (text []byte, err error) { 226 | text = []byte(u.String()) 227 | return 228 | } 229 | 230 | // UnmarshalText implements the encoding.TextUnmarshaler interface. 231 | // Following formats are supported: 232 | // "6ba7b810-9dad-11d1-80b4-00c04fd430c8", 233 | // "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", 234 | // "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" 235 | func (u *UUID) UnmarshalText(text []byte) (err error) { 236 | if len(text) < 32 { 237 | err = fmt.Errorf("uuid: UUID string too short: %s", text) 238 | return 239 | } 240 | 241 | t := text[:] 242 | braced := false 243 | 244 | if bytes.Equal(t[:9], urnPrefix) { 245 | t = t[9:] 246 | } else if t[0] == '{' { 247 | braced = true 248 | t = t[1:] 249 | } 250 | 251 | b := u[:] 252 | 253 | for i, byteGroup := range byteGroups { 254 | if i > 0 { 255 | if t[0] != '-' { 256 | err = fmt.Errorf("uuid: invalid string format") 257 | return 258 | } 259 | t = t[1:] 260 | } 261 | 262 | if len(t) < byteGroup { 263 | err = fmt.Errorf("uuid: UUID string too short: %s", text) 264 | return 265 | } 266 | 267 | if i == 4 && len(t) > byteGroup && 268 | ((braced && t[byteGroup] != '}') || len(t[byteGroup:]) > 1 || !braced) { 269 | err = fmt.Errorf("uuid: UUID string too long: %s", text) 270 | return 271 | } 272 | 273 | _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup]) 274 | if err != nil { 275 | return 276 | } 277 | 278 | t = t[byteGroup:] 279 | b = b[byteGroup/2:] 280 | } 281 | 282 | return 283 | } 284 | 285 | // MarshalBinary implements the encoding.BinaryMarshaler interface. 286 | func (u UUID) MarshalBinary() (data []byte, err error) { 287 | data = u.Bytes() 288 | return 289 | } 290 | 291 | // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. 292 | // It will return error if the slice isn't 16 bytes long. 293 | func (u *UUID) UnmarshalBinary(data []byte) (err error) { 294 | if len(data) != 16 { 295 | err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) 296 | return 297 | } 298 | copy(u[:], data) 299 | 300 | return 301 | } 302 | 303 | // Value implements the driver.Valuer interface. 304 | func (u UUID) Value() (driver.Value, error) { 305 | return u.String(), nil 306 | } 307 | 308 | // Scan implements the sql.Scanner interface. 309 | // A 16-byte slice is handled by UnmarshalBinary, while 310 | // a longer byte slice or a string is handled by UnmarshalText. 311 | func (u *UUID) Scan(src interface{}) error { 312 | switch src := src.(type) { 313 | case []byte: 314 | if len(src) == 16 { 315 | return u.UnmarshalBinary(src) 316 | } 317 | return u.UnmarshalText(src) 318 | 319 | case string: 320 | return u.UnmarshalText([]byte(src)) 321 | } 322 | 323 | return fmt.Errorf("uuid: cannot convert %T to UUID", src) 324 | } 325 | 326 | // Value implements the driver.Valuer interface. 327 | func (u NullUUID) Value() (driver.Value, error) { 328 | if !u.Valid { 329 | return nil, nil 330 | } 331 | // Delegate to UUID Value function 332 | return u.UUID.Value() 333 | } 334 | 335 | // Scan implements the sql.Scanner interface. 336 | func (u *NullUUID) Scan(src interface{}) error { 337 | if src == nil { 338 | u.UUID, u.Valid = Nil, false 339 | return nil 340 | } 341 | 342 | // Delegate to UUID Scan function 343 | u.Valid = true 344 | return u.UUID.Scan(src) 345 | } 346 | 347 | // FromBytes returns UUID converted from raw byte slice input. 348 | // It will return error if the slice isn't 16 bytes long. 349 | func FromBytes(input []byte) (u UUID, err error) { 350 | err = u.UnmarshalBinary(input) 351 | return 352 | } 353 | 354 | // FromBytesOrNil returns UUID converted from raw byte slice input. 355 | // Same behavior as FromBytes, but returns a Nil UUID on error. 356 | func FromBytesOrNil(input []byte) UUID { 357 | uuid, err := FromBytes(input) 358 | if err != nil { 359 | return Nil 360 | } 361 | return uuid 362 | } 363 | 364 | // FromString returns UUID parsed from string input. 365 | // Input is expected in a form accepted by UnmarshalText. 366 | func FromString(input string) (u UUID, err error) { 367 | err = u.UnmarshalText([]byte(input)) 368 | return 369 | } 370 | 371 | // FromStringOrNil returns UUID parsed from string input. 372 | // Same behavior as FromString, but returns a Nil UUID on error. 373 | func FromStringOrNil(input string) UUID { 374 | uuid, err := FromString(input) 375 | if err != nil { 376 | return Nil 377 | } 378 | return uuid 379 | } 380 | 381 | // Returns UUID v1/v2 storage state. 382 | // Returns epoch timestamp, clock sequence, and hardware address. 383 | func getStorage() (uint64, uint16, []byte) { 384 | storageOnce.Do(initStorage) 385 | 386 | storageMutex.Lock() 387 | defer storageMutex.Unlock() 388 | 389 | timeNow := epochFunc() 390 | // Clock changed backwards since last UUID generation. 391 | // Should increase clock sequence. 392 | if timeNow <= lastTime { 393 | clockSequence++ 394 | } 395 | lastTime = timeNow 396 | 397 | return timeNow, clockSequence, hardwareAddr[:] 398 | } 399 | 400 | func GetGUID() string { 401 | return NewV1().String() 402 | } 403 | 404 | // NewV1 returns UUID based on current timestamp and MAC address. 405 | func NewV1() UUID { 406 | u := UUID{} 407 | 408 | timeNow, clockSeq, hardwareAddr := getStorage() 409 | 410 | binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) 411 | binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) 412 | binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) 413 | binary.BigEndian.PutUint16(u[8:], clockSeq) 414 | 415 | copy(u[10:], hardwareAddr) 416 | 417 | u.SetVersion(1) 418 | u.SetVariant() 419 | 420 | return u 421 | } 422 | 423 | // NewV2 returns DCE Security UUID based on POSIX UID/GID. 424 | func NewV2(domain byte) UUID { 425 | u := UUID{} 426 | 427 | timeNow, clockSeq, hardwareAddr := getStorage() 428 | 429 | switch domain { 430 | case DomainPerson: 431 | binary.BigEndian.PutUint32(u[0:], posixUID) 432 | case DomainGroup: 433 | binary.BigEndian.PutUint32(u[0:], posixGID) 434 | } 435 | 436 | binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) 437 | binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) 438 | binary.BigEndian.PutUint16(u[8:], clockSeq) 439 | u[9] = domain 440 | 441 | copy(u[10:], hardwareAddr) 442 | 443 | u.SetVersion(2) 444 | u.SetVariant() 445 | 446 | return u 447 | } 448 | 449 | // NewV3 returns UUID based on MD5 hash of namespace UUID and name. 450 | func NewV3(ns UUID, name string) UUID { 451 | u := newFromHash(md5.New(), ns, name) 452 | u.SetVersion(3) 453 | u.SetVariant() 454 | 455 | return u 456 | } 457 | 458 | // NewV4 returns random generated UUID. 459 | func NewV4() UUID { 460 | u := UUID{} 461 | safeRandom(u[:]) 462 | u.SetVersion(4) 463 | u.SetVariant() 464 | 465 | return u 466 | } 467 | 468 | // NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. 469 | func NewV5(ns UUID, name string) UUID { 470 | u := newFromHash(sha1.New(), ns, name) 471 | u.SetVersion(5) 472 | u.SetVariant() 473 | 474 | return u 475 | } 476 | 477 | // Returns UUID based on hashing of namespace UUID and name. 478 | func newFromHash(h hash.Hash, ns UUID, name string) UUID { 479 | u := UUID{} 480 | h.Write(ns[:]) 481 | h.Write([]byte(name)) 482 | copy(u[:], h.Sum(nil)) 483 | 484 | return u 485 | } 486 | -------------------------------------------------------------------------------- /util/uuid_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013, 2015 by Maxim Bublis 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining 4 | // a copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to 8 | // permit persons to whom the Software is furnished to do so, subject to 9 | // the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be 12 | // included in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | package util 23 | 24 | import ( 25 | "bytes" 26 | "fmt" 27 | "testing" 28 | "time" 29 | "sort" 30 | ) 31 | 32 | func TestBytes(t *testing.T) { 33 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 34 | 35 | bytes1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 36 | 37 | if !bytes.Equal(u.Bytes(), bytes1) { 38 | t.Errorf("Incorrect bytes representation for UUID: %s", u) 39 | } 40 | } 41 | 42 | func TestString(t *testing.T) { 43 | if NamespaceDNS.String() != "6ba7b810-9dad-11d1-80b4-00c04fd430c8" { 44 | t.Errorf("Incorrect string representation for UUID: %s", NamespaceDNS.String()) 45 | } 46 | } 47 | 48 | func TestEqual(t *testing.T) { 49 | if !Equal(NamespaceDNS, NamespaceDNS) { 50 | t.Errorf("Incorrect comparison of %s and %s", NamespaceDNS, NamespaceDNS) 51 | } 52 | 53 | if Equal(NamespaceDNS, NamespaceURL) { 54 | t.Errorf("Incorrect comparison of %s and %s", NamespaceDNS, NamespaceURL) 55 | } 56 | } 57 | 58 | func TestOr(t *testing.T) { 59 | u1 := UUID{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff} 60 | u2 := UUID{0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00} 61 | 62 | u := UUID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 63 | 64 | if !Equal(u, Or(u1, u2)) { 65 | t.Errorf("Incorrect bitwise OR result %s", Or(u1, u2)) 66 | } 67 | } 68 | 69 | func TestAnd(t *testing.T) { 70 | u1 := UUID{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff} 71 | u2 := UUID{0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00} 72 | 73 | u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 74 | 75 | if !Equal(u, And(u1, u2)) { 76 | t.Errorf("Incorrect bitwise AND result %s", And(u1, u2)) 77 | } 78 | } 79 | 80 | func TestVersion(t *testing.T) { 81 | u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 82 | 83 | if u.Version() != 1 { 84 | t.Errorf("Incorrect version for UUID: %d", u.Version()) 85 | } 86 | } 87 | 88 | func TestSetVersion(t *testing.T) { 89 | u := UUID{} 90 | u.SetVersion(4) 91 | 92 | if u.Version() != 4 { 93 | t.Errorf("Incorrect version for UUID after u.setVersion(4): %d", u.Version()) 94 | } 95 | } 96 | 97 | func TestVariant(t *testing.T) { 98 | u1 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 99 | 100 | if u1.Variant() != VariantNCS { 101 | t.Errorf("Incorrect variant for UUID variant %d: %d", VariantNCS, u1.Variant()) 102 | } 103 | 104 | u2 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 105 | 106 | if u2.Variant() != VariantRFC4122 { 107 | t.Errorf("Incorrect variant for UUID variant %d: %d", VariantRFC4122, u2.Variant()) 108 | } 109 | 110 | u3 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 111 | 112 | if u3.Variant() != VariantMicrosoft { 113 | t.Errorf("Incorrect variant for UUID variant %d: %d", VariantMicrosoft, u3.Variant()) 114 | } 115 | 116 | u4 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 117 | 118 | if u4.Variant() != VariantFuture { 119 | t.Errorf("Incorrect variant for UUID variant %d: %d", VariantFuture, u4.Variant()) 120 | } 121 | } 122 | 123 | func TestSetVariant(t *testing.T) { 124 | u := new(UUID) 125 | u.SetVariant() 126 | 127 | if u.Variant() != VariantRFC4122 { 128 | t.Errorf("Incorrect variant for UUID after u.setVariant(): %d", u.Variant()) 129 | } 130 | } 131 | 132 | func TestFromBytes(t *testing.T) { 133 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 134 | b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 135 | 136 | u1, err := FromBytes(b1) 137 | if err != nil { 138 | t.Errorf("Error parsing UUID from bytes: %s", err) 139 | } 140 | 141 | if !Equal(u, u1) { 142 | t.Errorf("UUIDs should be equal: %s and %s", u, u1) 143 | } 144 | 145 | b2 := []byte{} 146 | 147 | _, err = FromBytes(b2) 148 | if err == nil { 149 | t.Errorf("Should return error parsing from empty byte slice, got %s", err) 150 | } 151 | } 152 | 153 | func TestMarshalBinary(t *testing.T) { 154 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 155 | b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 156 | 157 | b2, err := u.MarshalBinary() 158 | if err != nil { 159 | t.Errorf("Error marshaling UUID: %s", err) 160 | } 161 | 162 | if !bytes.Equal(b1, b2) { 163 | t.Errorf("Marshaled UUID should be %s, got %s", b1, b2) 164 | } 165 | } 166 | 167 | func TestUnmarshalBinary(t *testing.T) { 168 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 169 | b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 170 | 171 | u1 := UUID{} 172 | err := u1.UnmarshalBinary(b1) 173 | if err != nil { 174 | t.Errorf("Error unmarshaling UUID: %s", err) 175 | } 176 | 177 | if !Equal(u, u1) { 178 | t.Errorf("UUIDs should be equal: %s and %s", u, u1) 179 | } 180 | 181 | b2 := []byte{} 182 | u2 := UUID{} 183 | 184 | err = u2.UnmarshalBinary(b2) 185 | if err == nil { 186 | t.Errorf("Should return error unmarshalling from empty byte slice, got %s", err) 187 | } 188 | } 189 | 190 | func TestFromString(t *testing.T) { 191 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 192 | 193 | s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" 194 | s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" 195 | s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" 196 | 197 | _, err := FromString("") 198 | if err == nil { 199 | t.Errorf("Should return error trying to parse empty string, got %s", err) 200 | } 201 | 202 | u1, err := FromString(s1) 203 | if err != nil { 204 | t.Errorf("Error parsing UUID from string: %s", err) 205 | } 206 | 207 | if !Equal(u, u1) { 208 | t.Errorf("UUIDs should be equal: %s and %s", u, u1) 209 | } 210 | 211 | u2, err := FromString(s2) 212 | if err != nil { 213 | t.Errorf("Error parsing UUID from string: %s", err) 214 | } 215 | 216 | if !Equal(u, u2) { 217 | t.Errorf("UUIDs should be equal: %s and %s", u, u2) 218 | } 219 | 220 | u3, err := FromString(s3) 221 | if err != nil { 222 | t.Errorf("Error parsing UUID from string: %s", err) 223 | } 224 | 225 | if !Equal(u, u3) { 226 | t.Errorf("UUIDs should be equal: %s and %s", u, u3) 227 | } 228 | } 229 | 230 | func TestFromStringShort(t *testing.T) { 231 | // Invalid 35-character UUID string 232 | s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c" 233 | 234 | for i := len(s1); i >= 0; i-- { 235 | _, err := FromString(s1[:i]) 236 | if err == nil { 237 | t.Errorf("Should return error trying to parse too short string, got %s", err) 238 | } 239 | } 240 | } 241 | 242 | func TestFromStringLong(t *testing.T) { 243 | // Invalid 37+ character UUID string 244 | s := []string{ 245 | "6ba7b810-9dad-11d1-80b4-00c04fd430c8=", 246 | "6ba7b810-9dad-11d1-80b4-00c04fd430c8}", 247 | "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f", 248 | "6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8", 249 | } 250 | 251 | for _, str := range s { 252 | _, err := FromString(str) 253 | if err == nil { 254 | t.Errorf("Should return error trying to parse too long string, passed %s", str) 255 | } 256 | } 257 | } 258 | 259 | func TestFromStringInvalid(t *testing.T) { 260 | // Invalid UUID string formats 261 | s := []string{ 262 | "6ba7b8109dad11d180b400c04fd430c8", 263 | "6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8", 264 | "urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", 265 | "6ba7b8109-dad-11d1-80b4-00c04fd430c8", 266 | "6ba7b810-9dad1-1d1-80b4-00c04fd430c8", 267 | "6ba7b810-9dad-11d18-0b4-00c04fd430c8", 268 | "6ba7b810-9dad-11d1-80b40-0c04fd430c8", 269 | "6ba7b810+9dad+11d1+80b4+00c04fd430c8", 270 | "6ba7b810-9dad11d180b400c04fd430c8", 271 | "6ba7b8109dad-11d180b400c04fd430c8", 272 | "6ba7b8109dad11d1-80b400c04fd430c8", 273 | "6ba7b8109dad11d180b4-00c04fd430c8", 274 | } 275 | 276 | for _, str := range s { 277 | _, err := FromString(str) 278 | if err == nil { 279 | t.Errorf("Should return error trying to parse invalid string, passed %s", str) 280 | } 281 | } 282 | } 283 | 284 | func TestFromStringOrNil(t *testing.T) { 285 | u := FromStringOrNil("") 286 | if u != Nil { 287 | t.Errorf("Should return Nil UUID on parse failure, got %s", u) 288 | } 289 | } 290 | 291 | func TestFromBytesOrNil(t *testing.T) { 292 | b := []byte{} 293 | u := FromBytesOrNil(b) 294 | if u != Nil { 295 | t.Errorf("Should return Nil UUID on parse failure, got %s", u) 296 | } 297 | } 298 | 299 | func TestMarshalText(t *testing.T) { 300 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 301 | b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 302 | 303 | b2, err := u.MarshalText() 304 | if err != nil { 305 | t.Errorf("Error marshaling UUID: %s", err) 306 | } 307 | 308 | if !bytes.Equal(b1, b2) { 309 | t.Errorf("Marshaled UUID should be %s, got %s", b1, b2) 310 | } 311 | } 312 | 313 | func TestUnmarshalText(t *testing.T) { 314 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 315 | b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 316 | 317 | u1 := UUID{} 318 | err := u1.UnmarshalText(b1) 319 | if err != nil { 320 | t.Errorf("Error unmarshaling UUID: %s", err) 321 | } 322 | 323 | if !Equal(u, u1) { 324 | t.Errorf("UUIDs should be equal: %s and %s", u, u1) 325 | } 326 | 327 | b2 := []byte("") 328 | u2 := UUID{} 329 | 330 | err = u2.UnmarshalText(b2) 331 | if err == nil { 332 | t.Errorf("Should return error trying to unmarshal from empty string") 333 | } 334 | } 335 | 336 | func TestValue(t *testing.T) { 337 | u, err := FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 338 | if err != nil { 339 | t.Errorf("Error parsing UUID from string: %s", err) 340 | } 341 | 342 | val, err := u.Value() 343 | if err != nil { 344 | t.Errorf("Error getting UUID value: %s", err) 345 | } 346 | 347 | if val != u.String() { 348 | t.Errorf("Wrong value returned, should be equal: %s and %s", val, u) 349 | } 350 | } 351 | 352 | func TestValueNil(t *testing.T) { 353 | u := UUID{} 354 | 355 | val, err := u.Value() 356 | if err != nil { 357 | t.Errorf("Error getting UUID value: %s", err) 358 | } 359 | 360 | if val != Nil.String() { 361 | t.Errorf("Wrong value returned, should be equal to UUID.Nil: %s", val) 362 | } 363 | } 364 | 365 | func TestNullUUIDValueNil(t *testing.T) { 366 | u := NullUUID{} 367 | 368 | val, err := u.Value() 369 | if err != nil { 370 | t.Errorf("Error getting UUID value: %s", err) 371 | } 372 | 373 | if val != nil { 374 | t.Errorf("Wrong value returned, should be nil: %s", val) 375 | } 376 | } 377 | 378 | func TestScanBinary(t *testing.T) { 379 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 380 | b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 381 | 382 | u1 := UUID{} 383 | err := u1.Scan(b1) 384 | if err != nil { 385 | t.Errorf("Error unmarshaling UUID: %s", err) 386 | } 387 | 388 | if !Equal(u, u1) { 389 | t.Errorf("UUIDs should be equal: %s and %s", u, u1) 390 | } 391 | 392 | b2 := []byte{} 393 | u2 := UUID{} 394 | 395 | err = u2.Scan(b2) 396 | if err == nil { 397 | t.Errorf("Should return error unmarshalling from empty byte slice, got %s", err) 398 | } 399 | } 400 | 401 | func TestScanString(t *testing.T) { 402 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 403 | s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" 404 | 405 | u1 := UUID{} 406 | err := u1.Scan(s1) 407 | if err != nil { 408 | t.Errorf("Error unmarshaling UUID: %s", err) 409 | } 410 | 411 | if !Equal(u, u1) { 412 | t.Errorf("UUIDs should be equal: %s and %s", u, u1) 413 | } 414 | 415 | s2 := "" 416 | u2 := UUID{} 417 | 418 | err = u2.Scan(s2) 419 | if err == nil { 420 | t.Errorf("Should return error trying to unmarshal from empty string") 421 | } 422 | } 423 | 424 | func TestScanText(t *testing.T) { 425 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 426 | b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 427 | 428 | u1 := UUID{} 429 | err := u1.Scan(b1) 430 | if err != nil { 431 | t.Errorf("Error unmarshaling UUID: %s", err) 432 | } 433 | 434 | if !Equal(u, u1) { 435 | t.Errorf("UUIDs should be equal: %s and %s", u, u1) 436 | } 437 | 438 | b2 := []byte("") 439 | u2 := UUID{} 440 | 441 | err = u2.Scan(b2) 442 | if err == nil { 443 | t.Errorf("Should return error trying to unmarshal from empty string") 444 | } 445 | } 446 | 447 | func TestScanUnsupported(t *testing.T) { 448 | u := UUID{} 449 | 450 | err := u.Scan(true) 451 | if err == nil { 452 | t.Errorf("Should return error trying to unmarshal from bool") 453 | } 454 | } 455 | 456 | func TestScanNil(t *testing.T) { 457 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 458 | 459 | err := u.Scan(nil) 460 | if err == nil { 461 | t.Errorf("Error UUID shouldn't allow unmarshalling from nil") 462 | } 463 | } 464 | 465 | func TestNullUUIDScanValid(t *testing.T) { 466 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} 467 | s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" 468 | 469 | u1 := NullUUID{} 470 | err := u1.Scan(s1) 471 | if err != nil { 472 | t.Errorf("Error unmarshaling NullUUID: %s", err) 473 | } 474 | 475 | if !u1.Valid { 476 | t.Errorf("NullUUID should be valid") 477 | } 478 | 479 | if !Equal(u, u1.UUID) { 480 | t.Errorf("UUIDs should be equal: %s and %s", u, u1.UUID) 481 | } 482 | } 483 | 484 | func TestNullUUIDScanNil(t *testing.T) { 485 | u := NullUUID{UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, true} 486 | 487 | err := u.Scan(nil) 488 | if err != nil { 489 | t.Errorf("Error unmarshaling NullUUID: %s", err) 490 | } 491 | 492 | if u.Valid { 493 | t.Errorf("NullUUID should not be valid") 494 | } 495 | 496 | if !Equal(u.UUID, Nil) { 497 | t.Errorf("NullUUID value should be equal to Nil: %v", u) 498 | } 499 | } 500 | 501 | func TestNewV1(t *testing.T) { 502 | u := NewV1() 503 | 504 | if u.Version() != 1 { 505 | t.Errorf("UUIDv1 generated with incorrect version: %d", u.Version()) 506 | } 507 | 508 | if u.Variant() != VariantRFC4122 { 509 | t.Errorf("UUIDv1 generated with incorrect variant: %d", u.Variant()) 510 | } 511 | 512 | u1 := NewV1() 513 | u2 := NewV1() 514 | 515 | if Equal(u1, u2) { 516 | t.Errorf("UUIDv1 generated two equal UUIDs: %s and %s", u1, u2) 517 | } 518 | 519 | oldFunc := epochFunc 520 | epochFunc = func() uint64 { return 0 } 521 | 522 | u3 := NewV1() 523 | u4 := NewV1() 524 | 525 | if Equal(u3, u4) { 526 | t.Errorf("UUIDv1 generated two equal UUIDs: %s and %s", u3, u4) 527 | } 528 | 529 | epochFunc = oldFunc 530 | } 531 | 532 | func TestNewV2(t *testing.T) { 533 | u1 := NewV2(DomainPerson) 534 | 535 | if u1.Version() != 2 { 536 | t.Errorf("UUIDv2 generated with incorrect version: %d", u1.Version()) 537 | } 538 | 539 | if u1.Variant() != VariantRFC4122 { 540 | t.Errorf("UUIDv2 generated with incorrect variant: %d", u1.Variant()) 541 | } 542 | 543 | u2 := NewV2(DomainGroup) 544 | 545 | if u2.Version() != 2 { 546 | t.Errorf("UUIDv2 generated with incorrect version: %d", u2.Version()) 547 | } 548 | 549 | if u2.Variant() != VariantRFC4122 { 550 | t.Errorf("UUIDv2 generated with incorrect variant: %d", u2.Variant()) 551 | } 552 | } 553 | 554 | func TestNewV3(t *testing.T) { 555 | u := NewV3(NamespaceDNS, "www.example.com") 556 | 557 | if u.Version() != 3 { 558 | t.Errorf("UUIDv3 generated with incorrect version: %d", u.Version()) 559 | } 560 | 561 | if u.Variant() != VariantRFC4122 { 562 | t.Errorf("UUIDv3 generated with incorrect variant: %d", u.Variant()) 563 | } 564 | 565 | if u.String() != "5df41881-3aed-3515-88a7-2f4a814cf09e" { 566 | t.Errorf("UUIDv3 generated incorrectly: %s", u.String()) 567 | } 568 | 569 | u = NewV3(NamespaceDNS, "python.org") 570 | 571 | if u.String() != "6fa459ea-ee8a-3ca4-894e-db77e160355e" { 572 | t.Errorf("UUIDv3 generated incorrectly: %s", u.String()) 573 | } 574 | 575 | u1 := NewV3(NamespaceDNS, "golang.org") 576 | u2 := NewV3(NamespaceDNS, "golang.org") 577 | if !Equal(u1, u2) { 578 | t.Errorf("UUIDv3 generated different UUIDs for same namespace and name: %s and %s", u1, u2) 579 | } 580 | 581 | u3 := NewV3(NamespaceDNS, "example.com") 582 | if Equal(u1, u3) { 583 | t.Errorf("UUIDv3 generated same UUIDs for different names in same namespace: %s and %s", u1, u2) 584 | } 585 | 586 | u4 := NewV3(NamespaceURL, "golang.org") 587 | if Equal(u1, u4) { 588 | t.Errorf("UUIDv3 generated same UUIDs for sane names in different namespaces: %s and %s", u1, u4) 589 | } 590 | } 591 | 592 | func TestNewV4(t *testing.T) { 593 | u := NewV4() 594 | 595 | if u.Version() != 4 { 596 | t.Errorf("UUIDv4 generated with incorrect version: %d", u.Version()) 597 | } 598 | 599 | if u.Variant() != VariantRFC4122 { 600 | t.Errorf("UUIDv4 generated with incorrect variant: %d", u.Variant()) 601 | } 602 | } 603 | 604 | func TestNewV5(t *testing.T) { 605 | u := NewV5(NamespaceDNS, "www.example.com") 606 | 607 | if u.Version() != 5 { 608 | t.Errorf("UUIDv5 generated with incorrect version: %d", u.Version()) 609 | } 610 | 611 | if u.Variant() != VariantRFC4122 { 612 | t.Errorf("UUIDv5 generated with incorrect variant: %d", u.Variant()) 613 | } 614 | 615 | u = NewV5(NamespaceDNS, "python.org") 616 | 617 | if u.String() != "886313e1-3b8a-5372-9b90-0c9aee199e5d" { 618 | t.Errorf("UUIDv5 generated incorrectly: %s", u.String()) 619 | } 620 | 621 | u1 := NewV5(NamespaceDNS, "golang.org") 622 | u2 := NewV5(NamespaceDNS, "golang.org") 623 | if !Equal(u1, u2) { 624 | t.Errorf("UUIDv5 generated different UUIDs for same namespace and name: %s and %s", u1, u2) 625 | } 626 | 627 | u3 := NewV5(NamespaceDNS, "example.com") 628 | if Equal(u1, u3) { 629 | t.Errorf("UUIDv5 generated same UUIDs for different names in same namespace: %s and %s", u1, u2) 630 | } 631 | 632 | u4 := NewV5(NamespaceURL, "golang.org") 633 | if Equal(u1, u4) { 634 | t.Errorf("UUIDv3 generated same UUIDs for sane names in different namespaces: %s and %s", u1, u4) 635 | } 636 | } 637 | 638 | func TestV1N(t *testing.T) { 639 | ot := time.Now() 640 | fmt.Println("start ", ot) 641 | var m = make(map[string]string) 642 | for index := 0; index < 1000000; index++ { 643 | s := NewV1().String() 644 | if _, ok := m[s]; ok { 645 | fmt.Println("same ", index, s) 646 | break 647 | } 648 | m[s] = s 649 | } 650 | 651 | fmt.Println("finish ", time.Now().Sub(ot)) 652 | } 653 | 654 | func TestRandStr(t *testing.T) { 655 | for index := 0; index < 10; index++ { 656 | fmt.Println(GetRandomString(16)) 657 | } 658 | //100w次 一秒 659 | } 660 | type ST struct { 661 | id string 662 | } 663 | func TestSort(t *testing.T) { 664 | var list = []*ST{&ST{"s3"},&ST{"ss1"},&ST{"s2"}}; 665 | sort.Slice(list, func(i, j int) bool { 666 | return list[i].id 0 { 482 | dAtA[i] = 0xa 483 | i++ 484 | i = encodeVarintProtos(dAtA, i, uint64(len(m.Message))) 485 | i += copy(dAtA[i:], m.Message) 486 | } 487 | return i, nil 488 | } 489 | 490 | func (m *SayRequest) Marshal() (dAtA []byte, err error) { 491 | size := m.Size() 492 | dAtA = make([]byte, size) 493 | n, err := m.MarshalTo(dAtA) 494 | if err != nil { 495 | return nil, err 496 | } 497 | return dAtA[:n], nil 498 | } 499 | 500 | func (m *SayRequest) MarshalTo(dAtA []byte) (int, error) { 501 | var i int 502 | _ = i 503 | var l int 504 | _ = l 505 | if len(m.UserName) > 0 { 506 | dAtA[i] = 0xa 507 | i++ 508 | i = encodeVarintProtos(dAtA, i, uint64(len(m.UserName))) 509 | i += copy(dAtA[i:], m.UserName) 510 | } 511 | if len(m.Message) > 0 { 512 | dAtA[i] = 0x12 513 | i++ 514 | i = encodeVarintProtos(dAtA, i, uint64(len(m.Message))) 515 | i += copy(dAtA[i:], m.Message) 516 | } 517 | return i, nil 518 | } 519 | 520 | func (m *SayResponse) Marshal() (dAtA []byte, err error) { 521 | size := m.Size() 522 | dAtA = make([]byte, size) 523 | n, err := m.MarshalTo(dAtA) 524 | if err != nil { 525 | return nil, err 526 | } 527 | return dAtA[:n], nil 528 | } 529 | 530 | func (m *SayResponse) MarshalTo(dAtA []byte) (int, error) { 531 | var i int 532 | _ = i 533 | var l int 534 | _ = l 535 | if len(m.UserName) > 0 { 536 | dAtA[i] = 0xa 537 | i++ 538 | i = encodeVarintProtos(dAtA, i, uint64(len(m.UserName))) 539 | i += copy(dAtA[i:], m.UserName) 540 | } 541 | if len(m.Message) > 0 { 542 | dAtA[i] = 0x12 543 | i++ 544 | i = encodeVarintProtos(dAtA, i, uint64(len(m.Message))) 545 | i += copy(dAtA[i:], m.Message) 546 | } 547 | return i, nil 548 | } 549 | 550 | func (m *NickRequest) Marshal() (dAtA []byte, err error) { 551 | size := m.Size() 552 | dAtA = make([]byte, size) 553 | n, err := m.MarshalTo(dAtA) 554 | if err != nil { 555 | return nil, err 556 | } 557 | return dAtA[:n], nil 558 | } 559 | 560 | func (m *NickRequest) MarshalTo(dAtA []byte) (int, error) { 561 | var i int 562 | _ = i 563 | var l int 564 | _ = l 565 | if len(m.OldUserName) > 0 { 566 | dAtA[i] = 0xa 567 | i++ 568 | i = encodeVarintProtos(dAtA, i, uint64(len(m.OldUserName))) 569 | i += copy(dAtA[i:], m.OldUserName) 570 | } 571 | if len(m.NewUserName) > 0 { 572 | dAtA[i] = 0x12 573 | i++ 574 | i = encodeVarintProtos(dAtA, i, uint64(len(m.NewUserName))) 575 | i += copy(dAtA[i:], m.NewUserName) 576 | } 577 | return i, nil 578 | } 579 | 580 | func (m *NickResponse) Marshal() (dAtA []byte, err error) { 581 | size := m.Size() 582 | dAtA = make([]byte, size) 583 | n, err := m.MarshalTo(dAtA) 584 | if err != nil { 585 | return nil, err 586 | } 587 | return dAtA[:n], nil 588 | } 589 | 590 | func (m *NickResponse) MarshalTo(dAtA []byte) (int, error) { 591 | var i int 592 | _ = i 593 | var l int 594 | _ = l 595 | if len(m.OldUserName) > 0 { 596 | dAtA[i] = 0xa 597 | i++ 598 | i = encodeVarintProtos(dAtA, i, uint64(len(m.OldUserName))) 599 | i += copy(dAtA[i:], m.OldUserName) 600 | } 601 | if len(m.NewUserName) > 0 { 602 | dAtA[i] = 0x12 603 | i++ 604 | i = encodeVarintProtos(dAtA, i, uint64(len(m.NewUserName))) 605 | i += copy(dAtA[i:], m.NewUserName) 606 | } 607 | return i, nil 608 | } 609 | 610 | func encodeFixed64Protos(dAtA []byte, offset int, v uint64) int { 611 | dAtA[offset] = uint8(v) 612 | dAtA[offset+1] = uint8(v >> 8) 613 | dAtA[offset+2] = uint8(v >> 16) 614 | dAtA[offset+3] = uint8(v >> 24) 615 | dAtA[offset+4] = uint8(v >> 32) 616 | dAtA[offset+5] = uint8(v >> 40) 617 | dAtA[offset+6] = uint8(v >> 48) 618 | dAtA[offset+7] = uint8(v >> 56) 619 | return offset + 8 620 | } 621 | func encodeFixed32Protos(dAtA []byte, offset int, v uint32) int { 622 | dAtA[offset] = uint8(v) 623 | dAtA[offset+1] = uint8(v >> 8) 624 | dAtA[offset+2] = uint8(v >> 16) 625 | dAtA[offset+3] = uint8(v >> 24) 626 | return offset + 4 627 | } 628 | func encodeVarintProtos(dAtA []byte, offset int, v uint64) int { 629 | for v >= 1<<7 { 630 | dAtA[offset] = uint8(v&0x7f | 0x80) 631 | v >>= 7 632 | offset++ 633 | } 634 | dAtA[offset] = uint8(v) 635 | return offset + 1 636 | } 637 | func (m *Connect) Size() (n int) { 638 | var l int 639 | _ = l 640 | if m.Sender != nil { 641 | l = m.Sender.Size() 642 | n += 1 + l + sovProtos(uint64(l)) 643 | } 644 | return n 645 | } 646 | 647 | func (m *Connected) Size() (n int) { 648 | var l int 649 | _ = l 650 | l = len(m.Message) 651 | if l > 0 { 652 | n += 1 + l + sovProtos(uint64(l)) 653 | } 654 | return n 655 | } 656 | 657 | func (m *SayRequest) Size() (n int) { 658 | var l int 659 | _ = l 660 | l = len(m.UserName) 661 | if l > 0 { 662 | n += 1 + l + sovProtos(uint64(l)) 663 | } 664 | l = len(m.Message) 665 | if l > 0 { 666 | n += 1 + l + sovProtos(uint64(l)) 667 | } 668 | return n 669 | } 670 | 671 | func (m *SayResponse) Size() (n int) { 672 | var l int 673 | _ = l 674 | l = len(m.UserName) 675 | if l > 0 { 676 | n += 1 + l + sovProtos(uint64(l)) 677 | } 678 | l = len(m.Message) 679 | if l > 0 { 680 | n += 1 + l + sovProtos(uint64(l)) 681 | } 682 | return n 683 | } 684 | 685 | func (m *NickRequest) Size() (n int) { 686 | var l int 687 | _ = l 688 | l = len(m.OldUserName) 689 | if l > 0 { 690 | n += 1 + l + sovProtos(uint64(l)) 691 | } 692 | l = len(m.NewUserName) 693 | if l > 0 { 694 | n += 1 + l + sovProtos(uint64(l)) 695 | } 696 | return n 697 | } 698 | 699 | func (m *NickResponse) Size() (n int) { 700 | var l int 701 | _ = l 702 | l = len(m.OldUserName) 703 | if l > 0 { 704 | n += 1 + l + sovProtos(uint64(l)) 705 | } 706 | l = len(m.NewUserName) 707 | if l > 0 { 708 | n += 1 + l + sovProtos(uint64(l)) 709 | } 710 | return n 711 | } 712 | 713 | func sovProtos(x uint64) (n int) { 714 | for { 715 | n++ 716 | x >>= 7 717 | if x == 0 { 718 | break 719 | } 720 | } 721 | return n 722 | } 723 | func sozProtos(x uint64) (n int) { 724 | return sovProtos(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 725 | } 726 | func (this *Connect) String() string { 727 | if this == nil { 728 | return "nil" 729 | } 730 | s := strings.Join([]string{`&Connect{`, 731 | `Sender:` + strings.Replace(fmt.Sprintf("%v", this.Sender), "PID", "actor.PID", 1) + `,`, 732 | `}`, 733 | }, "") 734 | return s 735 | } 736 | func (this *Connected) String() string { 737 | if this == nil { 738 | return "nil" 739 | } 740 | s := strings.Join([]string{`&Connected{`, 741 | `Message:` + fmt.Sprintf("%v", this.Message) + `,`, 742 | `}`, 743 | }, "") 744 | return s 745 | } 746 | func (this *SayRequest) String() string { 747 | if this == nil { 748 | return "nil" 749 | } 750 | s := strings.Join([]string{`&SayRequest{`, 751 | `UserName:` + fmt.Sprintf("%v", this.UserName) + `,`, 752 | `Message:` + fmt.Sprintf("%v", this.Message) + `,`, 753 | `}`, 754 | }, "") 755 | return s 756 | } 757 | func (this *SayResponse) String() string { 758 | if this == nil { 759 | return "nil" 760 | } 761 | s := strings.Join([]string{`&SayResponse{`, 762 | `UserName:` + fmt.Sprintf("%v", this.UserName) + `,`, 763 | `Message:` + fmt.Sprintf("%v", this.Message) + `,`, 764 | `}`, 765 | }, "") 766 | return s 767 | } 768 | func (this *NickRequest) String() string { 769 | if this == nil { 770 | return "nil" 771 | } 772 | s := strings.Join([]string{`&NickRequest{`, 773 | `OldUserName:` + fmt.Sprintf("%v", this.OldUserName) + `,`, 774 | `NewUserName:` + fmt.Sprintf("%v", this.NewUserName) + `,`, 775 | `}`, 776 | }, "") 777 | return s 778 | } 779 | func (this *NickResponse) String() string { 780 | if this == nil { 781 | return "nil" 782 | } 783 | s := strings.Join([]string{`&NickResponse{`, 784 | `OldUserName:` + fmt.Sprintf("%v", this.OldUserName) + `,`, 785 | `NewUserName:` + fmt.Sprintf("%v", this.NewUserName) + `,`, 786 | `}`, 787 | }, "") 788 | return s 789 | } 790 | func valueToStringProtos(v interface{}) string { 791 | rv := reflect.ValueOf(v) 792 | if rv.IsNil() { 793 | return "nil" 794 | } 795 | pv := reflect.Indirect(rv).Interface() 796 | return fmt.Sprintf("*%v", pv) 797 | } 798 | func (m *Connect) Unmarshal(dAtA []byte) error { 799 | l := len(dAtA) 800 | iNdEx := 0 801 | for iNdEx < l { 802 | preIndex := iNdEx 803 | var wire uint64 804 | for shift := uint(0); ; shift += 7 { 805 | if shift >= 64 { 806 | return ErrIntOverflowProtos 807 | } 808 | if iNdEx >= l { 809 | return io.ErrUnexpectedEOF 810 | } 811 | b := dAtA[iNdEx] 812 | iNdEx++ 813 | wire |= (uint64(b) & 0x7F) << shift 814 | if b < 0x80 { 815 | break 816 | } 817 | } 818 | fieldNum := int32(wire >> 3) 819 | wireType := int(wire & 0x7) 820 | if wireType == 4 { 821 | return fmt.Errorf("proto: Connect: wiretype end group for non-group") 822 | } 823 | if fieldNum <= 0 { 824 | return fmt.Errorf("proto: Connect: illegal tag %d (wire type %d)", fieldNum, wire) 825 | } 826 | switch fieldNum { 827 | case 1: 828 | if wireType != 2 { 829 | return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) 830 | } 831 | var msglen int 832 | for shift := uint(0); ; shift += 7 { 833 | if shift >= 64 { 834 | return ErrIntOverflowProtos 835 | } 836 | if iNdEx >= l { 837 | return io.ErrUnexpectedEOF 838 | } 839 | b := dAtA[iNdEx] 840 | iNdEx++ 841 | msglen |= (int(b) & 0x7F) << shift 842 | if b < 0x80 { 843 | break 844 | } 845 | } 846 | if msglen < 0 { 847 | return ErrInvalidLengthProtos 848 | } 849 | postIndex := iNdEx + msglen 850 | if postIndex > l { 851 | return io.ErrUnexpectedEOF 852 | } 853 | if m.Sender == nil { 854 | m.Sender = &actor.PID{} 855 | } 856 | if err := m.Sender.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { 857 | return err 858 | } 859 | iNdEx = postIndex 860 | default: 861 | iNdEx = preIndex 862 | skippy, err := skipProtos(dAtA[iNdEx:]) 863 | if err != nil { 864 | return err 865 | } 866 | if skippy < 0 { 867 | return ErrInvalidLengthProtos 868 | } 869 | if (iNdEx + skippy) > l { 870 | return io.ErrUnexpectedEOF 871 | } 872 | iNdEx += skippy 873 | } 874 | } 875 | 876 | if iNdEx > l { 877 | return io.ErrUnexpectedEOF 878 | } 879 | return nil 880 | } 881 | func (m *Connected) Unmarshal(dAtA []byte) error { 882 | l := len(dAtA) 883 | iNdEx := 0 884 | for iNdEx < l { 885 | preIndex := iNdEx 886 | var wire uint64 887 | for shift := uint(0); ; shift += 7 { 888 | if shift >= 64 { 889 | return ErrIntOverflowProtos 890 | } 891 | if iNdEx >= l { 892 | return io.ErrUnexpectedEOF 893 | } 894 | b := dAtA[iNdEx] 895 | iNdEx++ 896 | wire |= (uint64(b) & 0x7F) << shift 897 | if b < 0x80 { 898 | break 899 | } 900 | } 901 | fieldNum := int32(wire >> 3) 902 | wireType := int(wire & 0x7) 903 | if wireType == 4 { 904 | return fmt.Errorf("proto: Connected: wiretype end group for non-group") 905 | } 906 | if fieldNum <= 0 { 907 | return fmt.Errorf("proto: Connected: illegal tag %d (wire type %d)", fieldNum, wire) 908 | } 909 | switch fieldNum { 910 | case 1: 911 | if wireType != 2 { 912 | return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) 913 | } 914 | var stringLen uint64 915 | for shift := uint(0); ; shift += 7 { 916 | if shift >= 64 { 917 | return ErrIntOverflowProtos 918 | } 919 | if iNdEx >= l { 920 | return io.ErrUnexpectedEOF 921 | } 922 | b := dAtA[iNdEx] 923 | iNdEx++ 924 | stringLen |= (uint64(b) & 0x7F) << shift 925 | if b < 0x80 { 926 | break 927 | } 928 | } 929 | intStringLen := int(stringLen) 930 | if intStringLen < 0 { 931 | return ErrInvalidLengthProtos 932 | } 933 | postIndex := iNdEx + intStringLen 934 | if postIndex > l { 935 | return io.ErrUnexpectedEOF 936 | } 937 | m.Message = string(dAtA[iNdEx:postIndex]) 938 | iNdEx = postIndex 939 | default: 940 | iNdEx = preIndex 941 | skippy, err := skipProtos(dAtA[iNdEx:]) 942 | if err != nil { 943 | return err 944 | } 945 | if skippy < 0 { 946 | return ErrInvalidLengthProtos 947 | } 948 | if (iNdEx + skippy) > l { 949 | return io.ErrUnexpectedEOF 950 | } 951 | iNdEx += skippy 952 | } 953 | } 954 | 955 | if iNdEx > l { 956 | return io.ErrUnexpectedEOF 957 | } 958 | return nil 959 | } 960 | func (m *SayRequest) Unmarshal(dAtA []byte) error { 961 | l := len(dAtA) 962 | iNdEx := 0 963 | for iNdEx < l { 964 | preIndex := iNdEx 965 | var wire uint64 966 | for shift := uint(0); ; shift += 7 { 967 | if shift >= 64 { 968 | return ErrIntOverflowProtos 969 | } 970 | if iNdEx >= l { 971 | return io.ErrUnexpectedEOF 972 | } 973 | b := dAtA[iNdEx] 974 | iNdEx++ 975 | wire |= (uint64(b) & 0x7F) << shift 976 | if b < 0x80 { 977 | break 978 | } 979 | } 980 | fieldNum := int32(wire >> 3) 981 | wireType := int(wire & 0x7) 982 | if wireType == 4 { 983 | return fmt.Errorf("proto: SayRequest: wiretype end group for non-group") 984 | } 985 | if fieldNum <= 0 { 986 | return fmt.Errorf("proto: SayRequest: illegal tag %d (wire type %d)", fieldNum, wire) 987 | } 988 | switch fieldNum { 989 | case 1: 990 | if wireType != 2 { 991 | return fmt.Errorf("proto: wrong wireType = %d for field UserName", wireType) 992 | } 993 | var stringLen uint64 994 | for shift := uint(0); ; shift += 7 { 995 | if shift >= 64 { 996 | return ErrIntOverflowProtos 997 | } 998 | if iNdEx >= l { 999 | return io.ErrUnexpectedEOF 1000 | } 1001 | b := dAtA[iNdEx] 1002 | iNdEx++ 1003 | stringLen |= (uint64(b) & 0x7F) << shift 1004 | if b < 0x80 { 1005 | break 1006 | } 1007 | } 1008 | intStringLen := int(stringLen) 1009 | if intStringLen < 0 { 1010 | return ErrInvalidLengthProtos 1011 | } 1012 | postIndex := iNdEx + intStringLen 1013 | if postIndex > l { 1014 | return io.ErrUnexpectedEOF 1015 | } 1016 | m.UserName = string(dAtA[iNdEx:postIndex]) 1017 | iNdEx = postIndex 1018 | case 2: 1019 | if wireType != 2 { 1020 | return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) 1021 | } 1022 | var stringLen uint64 1023 | for shift := uint(0); ; shift += 7 { 1024 | if shift >= 64 { 1025 | return ErrIntOverflowProtos 1026 | } 1027 | if iNdEx >= l { 1028 | return io.ErrUnexpectedEOF 1029 | } 1030 | b := dAtA[iNdEx] 1031 | iNdEx++ 1032 | stringLen |= (uint64(b) & 0x7F) << shift 1033 | if b < 0x80 { 1034 | break 1035 | } 1036 | } 1037 | intStringLen := int(stringLen) 1038 | if intStringLen < 0 { 1039 | return ErrInvalidLengthProtos 1040 | } 1041 | postIndex := iNdEx + intStringLen 1042 | if postIndex > l { 1043 | return io.ErrUnexpectedEOF 1044 | } 1045 | m.Message = string(dAtA[iNdEx:postIndex]) 1046 | iNdEx = postIndex 1047 | default: 1048 | iNdEx = preIndex 1049 | skippy, err := skipProtos(dAtA[iNdEx:]) 1050 | if err != nil { 1051 | return err 1052 | } 1053 | if skippy < 0 { 1054 | return ErrInvalidLengthProtos 1055 | } 1056 | if (iNdEx + skippy) > l { 1057 | return io.ErrUnexpectedEOF 1058 | } 1059 | iNdEx += skippy 1060 | } 1061 | } 1062 | 1063 | if iNdEx > l { 1064 | return io.ErrUnexpectedEOF 1065 | } 1066 | return nil 1067 | } 1068 | func (m *SayResponse) Unmarshal(dAtA []byte) error { 1069 | l := len(dAtA) 1070 | iNdEx := 0 1071 | for iNdEx < l { 1072 | preIndex := iNdEx 1073 | var wire uint64 1074 | for shift := uint(0); ; shift += 7 { 1075 | if shift >= 64 { 1076 | return ErrIntOverflowProtos 1077 | } 1078 | if iNdEx >= l { 1079 | return io.ErrUnexpectedEOF 1080 | } 1081 | b := dAtA[iNdEx] 1082 | iNdEx++ 1083 | wire |= (uint64(b) & 0x7F) << shift 1084 | if b < 0x80 { 1085 | break 1086 | } 1087 | } 1088 | fieldNum := int32(wire >> 3) 1089 | wireType := int(wire & 0x7) 1090 | if wireType == 4 { 1091 | return fmt.Errorf("proto: SayResponse: wiretype end group for non-group") 1092 | } 1093 | if fieldNum <= 0 { 1094 | return fmt.Errorf("proto: SayResponse: illegal tag %d (wire type %d)", fieldNum, wire) 1095 | } 1096 | switch fieldNum { 1097 | case 1: 1098 | if wireType != 2 { 1099 | return fmt.Errorf("proto: wrong wireType = %d for field UserName", wireType) 1100 | } 1101 | var stringLen uint64 1102 | for shift := uint(0); ; shift += 7 { 1103 | if shift >= 64 { 1104 | return ErrIntOverflowProtos 1105 | } 1106 | if iNdEx >= l { 1107 | return io.ErrUnexpectedEOF 1108 | } 1109 | b := dAtA[iNdEx] 1110 | iNdEx++ 1111 | stringLen |= (uint64(b) & 0x7F) << shift 1112 | if b < 0x80 { 1113 | break 1114 | } 1115 | } 1116 | intStringLen := int(stringLen) 1117 | if intStringLen < 0 { 1118 | return ErrInvalidLengthProtos 1119 | } 1120 | postIndex := iNdEx + intStringLen 1121 | if postIndex > l { 1122 | return io.ErrUnexpectedEOF 1123 | } 1124 | m.UserName = string(dAtA[iNdEx:postIndex]) 1125 | iNdEx = postIndex 1126 | case 2: 1127 | if wireType != 2 { 1128 | return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) 1129 | } 1130 | var stringLen uint64 1131 | for shift := uint(0); ; shift += 7 { 1132 | if shift >= 64 { 1133 | return ErrIntOverflowProtos 1134 | } 1135 | if iNdEx >= l { 1136 | return io.ErrUnexpectedEOF 1137 | } 1138 | b := dAtA[iNdEx] 1139 | iNdEx++ 1140 | stringLen |= (uint64(b) & 0x7F) << shift 1141 | if b < 0x80 { 1142 | break 1143 | } 1144 | } 1145 | intStringLen := int(stringLen) 1146 | if intStringLen < 0 { 1147 | return ErrInvalidLengthProtos 1148 | } 1149 | postIndex := iNdEx + intStringLen 1150 | if postIndex > l { 1151 | return io.ErrUnexpectedEOF 1152 | } 1153 | m.Message = string(dAtA[iNdEx:postIndex]) 1154 | iNdEx = postIndex 1155 | default: 1156 | iNdEx = preIndex 1157 | skippy, err := skipProtos(dAtA[iNdEx:]) 1158 | if err != nil { 1159 | return err 1160 | } 1161 | if skippy < 0 { 1162 | return ErrInvalidLengthProtos 1163 | } 1164 | if (iNdEx + skippy) > l { 1165 | return io.ErrUnexpectedEOF 1166 | } 1167 | iNdEx += skippy 1168 | } 1169 | } 1170 | 1171 | if iNdEx > l { 1172 | return io.ErrUnexpectedEOF 1173 | } 1174 | return nil 1175 | } 1176 | func (m *NickRequest) Unmarshal(dAtA []byte) error { 1177 | l := len(dAtA) 1178 | iNdEx := 0 1179 | for iNdEx < l { 1180 | preIndex := iNdEx 1181 | var wire uint64 1182 | for shift := uint(0); ; shift += 7 { 1183 | if shift >= 64 { 1184 | return ErrIntOverflowProtos 1185 | } 1186 | if iNdEx >= l { 1187 | return io.ErrUnexpectedEOF 1188 | } 1189 | b := dAtA[iNdEx] 1190 | iNdEx++ 1191 | wire |= (uint64(b) & 0x7F) << shift 1192 | if b < 0x80 { 1193 | break 1194 | } 1195 | } 1196 | fieldNum := int32(wire >> 3) 1197 | wireType := int(wire & 0x7) 1198 | if wireType == 4 { 1199 | return fmt.Errorf("proto: NickRequest: wiretype end group for non-group") 1200 | } 1201 | if fieldNum <= 0 { 1202 | return fmt.Errorf("proto: NickRequest: illegal tag %d (wire type %d)", fieldNum, wire) 1203 | } 1204 | switch fieldNum { 1205 | case 1: 1206 | if wireType != 2 { 1207 | return fmt.Errorf("proto: wrong wireType = %d for field OldUserName", wireType) 1208 | } 1209 | var stringLen uint64 1210 | for shift := uint(0); ; shift += 7 { 1211 | if shift >= 64 { 1212 | return ErrIntOverflowProtos 1213 | } 1214 | if iNdEx >= l { 1215 | return io.ErrUnexpectedEOF 1216 | } 1217 | b := dAtA[iNdEx] 1218 | iNdEx++ 1219 | stringLen |= (uint64(b) & 0x7F) << shift 1220 | if b < 0x80 { 1221 | break 1222 | } 1223 | } 1224 | intStringLen := int(stringLen) 1225 | if intStringLen < 0 { 1226 | return ErrInvalidLengthProtos 1227 | } 1228 | postIndex := iNdEx + intStringLen 1229 | if postIndex > l { 1230 | return io.ErrUnexpectedEOF 1231 | } 1232 | m.OldUserName = string(dAtA[iNdEx:postIndex]) 1233 | iNdEx = postIndex 1234 | case 2: 1235 | if wireType != 2 { 1236 | return fmt.Errorf("proto: wrong wireType = %d for field NewUserName", wireType) 1237 | } 1238 | var stringLen uint64 1239 | for shift := uint(0); ; shift += 7 { 1240 | if shift >= 64 { 1241 | return ErrIntOverflowProtos 1242 | } 1243 | if iNdEx >= l { 1244 | return io.ErrUnexpectedEOF 1245 | } 1246 | b := dAtA[iNdEx] 1247 | iNdEx++ 1248 | stringLen |= (uint64(b) & 0x7F) << shift 1249 | if b < 0x80 { 1250 | break 1251 | } 1252 | } 1253 | intStringLen := int(stringLen) 1254 | if intStringLen < 0 { 1255 | return ErrInvalidLengthProtos 1256 | } 1257 | postIndex := iNdEx + intStringLen 1258 | if postIndex > l { 1259 | return io.ErrUnexpectedEOF 1260 | } 1261 | m.NewUserName = string(dAtA[iNdEx:postIndex]) 1262 | iNdEx = postIndex 1263 | default: 1264 | iNdEx = preIndex 1265 | skippy, err := skipProtos(dAtA[iNdEx:]) 1266 | if err != nil { 1267 | return err 1268 | } 1269 | if skippy < 0 { 1270 | return ErrInvalidLengthProtos 1271 | } 1272 | if (iNdEx + skippy) > l { 1273 | return io.ErrUnexpectedEOF 1274 | } 1275 | iNdEx += skippy 1276 | } 1277 | } 1278 | 1279 | if iNdEx > l { 1280 | return io.ErrUnexpectedEOF 1281 | } 1282 | return nil 1283 | } 1284 | func (m *NickResponse) Unmarshal(dAtA []byte) error { 1285 | l := len(dAtA) 1286 | iNdEx := 0 1287 | for iNdEx < l { 1288 | preIndex := iNdEx 1289 | var wire uint64 1290 | for shift := uint(0); ; shift += 7 { 1291 | if shift >= 64 { 1292 | return ErrIntOverflowProtos 1293 | } 1294 | if iNdEx >= l { 1295 | return io.ErrUnexpectedEOF 1296 | } 1297 | b := dAtA[iNdEx] 1298 | iNdEx++ 1299 | wire |= (uint64(b) & 0x7F) << shift 1300 | if b < 0x80 { 1301 | break 1302 | } 1303 | } 1304 | fieldNum := int32(wire >> 3) 1305 | wireType := int(wire & 0x7) 1306 | if wireType == 4 { 1307 | return fmt.Errorf("proto: NickResponse: wiretype end group for non-group") 1308 | } 1309 | if fieldNum <= 0 { 1310 | return fmt.Errorf("proto: NickResponse: illegal tag %d (wire type %d)", fieldNum, wire) 1311 | } 1312 | switch fieldNum { 1313 | case 1: 1314 | if wireType != 2 { 1315 | return fmt.Errorf("proto: wrong wireType = %d for field OldUserName", wireType) 1316 | } 1317 | var stringLen uint64 1318 | for shift := uint(0); ; shift += 7 { 1319 | if shift >= 64 { 1320 | return ErrIntOverflowProtos 1321 | } 1322 | if iNdEx >= l { 1323 | return io.ErrUnexpectedEOF 1324 | } 1325 | b := dAtA[iNdEx] 1326 | iNdEx++ 1327 | stringLen |= (uint64(b) & 0x7F) << shift 1328 | if b < 0x80 { 1329 | break 1330 | } 1331 | } 1332 | intStringLen := int(stringLen) 1333 | if intStringLen < 0 { 1334 | return ErrInvalidLengthProtos 1335 | } 1336 | postIndex := iNdEx + intStringLen 1337 | if postIndex > l { 1338 | return io.ErrUnexpectedEOF 1339 | } 1340 | m.OldUserName = string(dAtA[iNdEx:postIndex]) 1341 | iNdEx = postIndex 1342 | case 2: 1343 | if wireType != 2 { 1344 | return fmt.Errorf("proto: wrong wireType = %d for field NewUserName", wireType) 1345 | } 1346 | var stringLen uint64 1347 | for shift := uint(0); ; shift += 7 { 1348 | if shift >= 64 { 1349 | return ErrIntOverflowProtos 1350 | } 1351 | if iNdEx >= l { 1352 | return io.ErrUnexpectedEOF 1353 | } 1354 | b := dAtA[iNdEx] 1355 | iNdEx++ 1356 | stringLen |= (uint64(b) & 0x7F) << shift 1357 | if b < 0x80 { 1358 | break 1359 | } 1360 | } 1361 | intStringLen := int(stringLen) 1362 | if intStringLen < 0 { 1363 | return ErrInvalidLengthProtos 1364 | } 1365 | postIndex := iNdEx + intStringLen 1366 | if postIndex > l { 1367 | return io.ErrUnexpectedEOF 1368 | } 1369 | m.NewUserName = string(dAtA[iNdEx:postIndex]) 1370 | iNdEx = postIndex 1371 | default: 1372 | iNdEx = preIndex 1373 | skippy, err := skipProtos(dAtA[iNdEx:]) 1374 | if err != nil { 1375 | return err 1376 | } 1377 | if skippy < 0 { 1378 | return ErrInvalidLengthProtos 1379 | } 1380 | if (iNdEx + skippy) > l { 1381 | return io.ErrUnexpectedEOF 1382 | } 1383 | iNdEx += skippy 1384 | } 1385 | } 1386 | 1387 | if iNdEx > l { 1388 | return io.ErrUnexpectedEOF 1389 | } 1390 | return nil 1391 | } 1392 | func skipProtos(dAtA []byte) (n int, err error) { 1393 | l := len(dAtA) 1394 | iNdEx := 0 1395 | for iNdEx < l { 1396 | var wire uint64 1397 | for shift := uint(0); ; shift += 7 { 1398 | if shift >= 64 { 1399 | return 0, ErrIntOverflowProtos 1400 | } 1401 | if iNdEx >= l { 1402 | return 0, io.ErrUnexpectedEOF 1403 | } 1404 | b := dAtA[iNdEx] 1405 | iNdEx++ 1406 | wire |= (uint64(b) & 0x7F) << shift 1407 | if b < 0x80 { 1408 | break 1409 | } 1410 | } 1411 | wireType := int(wire & 0x7) 1412 | switch wireType { 1413 | case 0: 1414 | for shift := uint(0); ; shift += 7 { 1415 | if shift >= 64 { 1416 | return 0, ErrIntOverflowProtos 1417 | } 1418 | if iNdEx >= l { 1419 | return 0, io.ErrUnexpectedEOF 1420 | } 1421 | iNdEx++ 1422 | if dAtA[iNdEx-1] < 0x80 { 1423 | break 1424 | } 1425 | } 1426 | return iNdEx, nil 1427 | case 1: 1428 | iNdEx += 8 1429 | return iNdEx, nil 1430 | case 2: 1431 | var length int 1432 | for shift := uint(0); ; shift += 7 { 1433 | if shift >= 64 { 1434 | return 0, ErrIntOverflowProtos 1435 | } 1436 | if iNdEx >= l { 1437 | return 0, io.ErrUnexpectedEOF 1438 | } 1439 | b := dAtA[iNdEx] 1440 | iNdEx++ 1441 | length |= (int(b) & 0x7F) << shift 1442 | if b < 0x80 { 1443 | break 1444 | } 1445 | } 1446 | iNdEx += length 1447 | if length < 0 { 1448 | return 0, ErrInvalidLengthProtos 1449 | } 1450 | return iNdEx, nil 1451 | case 3: 1452 | for { 1453 | var innerWire uint64 1454 | var start int = iNdEx 1455 | for shift := uint(0); ; shift += 7 { 1456 | if shift >= 64 { 1457 | return 0, ErrIntOverflowProtos 1458 | } 1459 | if iNdEx >= l { 1460 | return 0, io.ErrUnexpectedEOF 1461 | } 1462 | b := dAtA[iNdEx] 1463 | iNdEx++ 1464 | innerWire |= (uint64(b) & 0x7F) << shift 1465 | if b < 0x80 { 1466 | break 1467 | } 1468 | } 1469 | innerWireType := int(innerWire & 0x7) 1470 | if innerWireType == 4 { 1471 | break 1472 | } 1473 | next, err := skipProtos(dAtA[start:]) 1474 | if err != nil { 1475 | return 0, err 1476 | } 1477 | iNdEx = start + next 1478 | } 1479 | return iNdEx, nil 1480 | case 4: 1481 | return iNdEx, nil 1482 | case 5: 1483 | iNdEx += 4 1484 | return iNdEx, nil 1485 | default: 1486 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 1487 | } 1488 | } 1489 | panic("unreachable") 1490 | } 1491 | 1492 | var ( 1493 | ErrInvalidLengthProtos = fmt.Errorf("proto: negative length found during unmarshaling") 1494 | ErrIntOverflowProtos = fmt.Errorf("proto: integer overflow") 1495 | ) 1496 | 1497 | func init() { proto.RegisterFile("protos.proto", fileDescriptorProtos) } 1498 | 1499 | var fileDescriptorProtos = []byte{ 1500 | // 288 bytes of a gzipped FileDescriptorProto 1501 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x28, 0xca, 0x2f, 1502 | 0xc9, 0x2f, 0xd6, 0x03, 0x53, 0x42, 0x1c, 0xb9, 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0xc5, 0x52, 1503 | 0x66, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x8e, 0xc5, 0x95, 0x79, 1504 | 0xd9, 0x45, 0xf9, 0x79, 0x9e, 0x21, 0xfa, 0x60, 0x65, 0x89, 0xc9, 0x25, 0xf9, 0x45, 0xba, 0xe9, 1505 | 0xf9, 0xfa, 0x60, 0x86, 0x3e, 0xb2, 0x09, 0x4a, 0xba, 0x5c, 0xec, 0xce, 0xf9, 0x79, 0x79, 0xa9, 1506 | 0xc9, 0x25, 0x42, 0x4a, 0x5c, 0x6c, 0xc1, 0xa9, 0x79, 0x29, 0xa9, 0x45, 0x12, 0x8c, 0x0a, 0x8c, 1507 | 0x1a, 0xdc, 0x46, 0x5c, 0x7a, 0x60, 0xf5, 0x7a, 0x01, 0x9e, 0x2e, 0x41, 0x50, 0x19, 0x25, 0x55, 1508 | 0x2e, 0x4e, 0xa8, 0xf2, 0xd4, 0x14, 0x21, 0x09, 0x2e, 0x76, 0x5f, 0x88, 0xfd, 0x60, 0x1d, 0x9c, 1509 | 0x41, 0x30, 0xae, 0x92, 0x13, 0x17, 0x57, 0x70, 0x62, 0x65, 0x50, 0x6a, 0x61, 0x69, 0x6a, 0x71, 1510 | 0x89, 0x90, 0x14, 0x17, 0x47, 0x68, 0x71, 0x6a, 0x91, 0x5f, 0x62, 0x2e, 0x4c, 0x21, 0x9c, 0x8f, 1511 | 0x6c, 0x06, 0x13, 0xaa, 0x19, 0xce, 0x5c, 0xdc, 0x60, 0x33, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 1512 | 0xc9, 0x34, 0x24, 0x90, 0x8b, 0xdb, 0x2f, 0x33, 0x39, 0x1b, 0xe6, 0x12, 0x05, 0x2e, 0x6e, 0xff, 1513 | 0x9c, 0x14, 0x34, 0x73, 0x90, 0x85, 0x40, 0x2a, 0xfc, 0x52, 0xcb, 0xe1, 0x2a, 0x20, 0xc6, 0x21, 1514 | 0x0b, 0x29, 0x05, 0x71, 0xf1, 0x40, 0x8c, 0x84, 0x3a, 0x8c, 0x0a, 0x66, 0x3a, 0xe9, 0x5c, 0x78, 1515 | 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c, 0x0d, 0x8f, 0xe4, 0x18, 0x57, 1516 | 0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 1517 | 0x5f, 0x3c, 0x92, 0x63, 0xf8, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x24, 0x36, 0x70, 1518 | 0xd4, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x7d, 0xf8, 0xe5, 0x04, 0x0c, 0x02, 0x00, 0x00, 1519 | } 1520 | --------------------------------------------------------------------------------