#StackBounty: #go #random Generate random 128 bit decimal in given range in go

Bounty: 100

Let’s say that we have a random number generator that can generate random 32 or 64 bit integers (like rand.Rand in the standard library)

Generating a random int64 in a given range [a,b] is fairly easy:

rand.Seed(time.Now().UnixNano())
n := rand.Int63n(b-a) + a

Is it possible to generate random 128 bit decimal (as defined in specification IEEE 754-2008) in a given range from a combination of 32 or 64 bit random integers?


Get this bounty!!!

#StackBounty: #linux #sockets #go #tcp Why accepted two same 5-tuple socket when concurrent connect to the server?

Bounty: 50

server.go

package main

import (
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net"
    "net/http"
    _ "net/http/pprof"
    "sync"
    "syscall"
)

type ConnSet struct {
    data  map[int]net.Conn
    mutex sync.Mutex
}

func (m *ConnSet) Update(id int, conn net.Conn) error {
    m.mutex.Lock()
    defer m.mutex.Unlock()
    if _, ok := m.data[id]; ok {
        fmt.Printf("add: key %d existed n", id)
        return fmt.Errorf("add: key %d existed n", id)
    }
    m.data[id] = conn
    return nil
}

var connSet = &ConnSet{
    data: make(map[int]net.Conn),
}

func main() {
    setLimit()

    ln, err := net.Listen("tcp", ":12345")
    if err != nil {
        panic(err)
    }

    go func() {
        if err := http.ListenAndServe(":6060", nil); err != nil {
            log.Fatalf("pprof failed: %v", err)
        }
    }()

    var connections []net.Conn
    defer func() {
        for _, conn := range connections {
            conn.Close()
        }
    }()

    for {
        conn, e := ln.Accept()
        if e != nil {
            if ne, ok := e.(net.Error); ok && ne.Temporary() {
                log.Printf("accept temp err: %v", ne)
                continue
            }

            log.Printf("accept err: %v", e)
            return
        }
        port := conn.RemoteAddr().(*net.TCPAddr).Port
        connSet.Update(port, conn)
        go handleConn(conn)
        connections = append(connections, conn)
        if len(connections)%100 == 0 {
            log.Printf("total number of connections: %v", len(connections))
        }
    }
}

func handleConn(conn net.Conn) {
    io.Copy(ioutil.Discard, conn)
}

func setLimit() {
    var rLimit syscall.Rlimit
    if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil {
        panic(err)
    }
    rLimit.Cur = rLimit.Max
    if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil {
        panic(err)
    }

    log.Printf("set cur limit: %d", rLimit.Cur)
}

client.go

package main

import (
    "bytes"
    "flag"
    "fmt"
    "io"
    "log"
    "net"
    "os"
    "strconv"
    "sync"
    "syscall"
    "time"
)

var portFlag = flag.Int("port", 12345, "port")

type ConnSet struct {
    data  map[int]net.Conn
    mutex sync.Mutex
}

func (m *ConnSet) Update(id int, conn net.Conn) error {
    m.mutex.Lock()
    defer m.mutex.Unlock()
    if _, ok := m.data[id]; ok {
        fmt.Printf("add: key %d existed n", id)
        return fmt.Errorf("add: key %d existed n", id)
    }
    m.data[id] = conn
    return nil
}

var connSet = &ConnSet{
    data: make(map[int]net.Conn),
}

func echoClient() {
    addr := fmt.Sprintf("127.0.0.1:%d", *portFlag)
    dialer := net.Dialer{}
    conn, err := dialer.Dial("tcp", addr)
    if err != nil {
        fmt.Println("ERROR", err)
        os.Exit(1)
    }
    port := conn.LocalAddr().(*net.TCPAddr).Port
    connSet.Update(port, conn)
    defer conn.Close()

    for i := 0; i < 10; i++ {
        s := fmt.Sprintf("%s", strconv.Itoa(i))
        _, err := conn.Write([]byte(s))
        if err != nil {
            log.Println("write error: ", err)
        }
        b := make([]byte, 1024)
        _, err = conn.Read(b)
        switch err {
        case nil:
            if string(bytes.Trim(b, "x00")) != s {
                log.Printf("resp req not equal, req: %d, res: %s", i, string(bytes.Trim(b, "x00")))
            }
        case io.EOF:
            fmt.Println("eof")
            break
        default:
            fmt.Println("ERROR", err)
            break
        }
    }
    time.Sleep(time.Hour)
    if err := conn.Close(); err != nil {
        log.Printf("client conn close err: %s", err)
    }
}

func main() {
    flag.Parse()
    setLimit()
    before := time.Now()
    var wg sync.WaitGroup
    for i := 0; i < 20000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            echoClient()
        }()
    }
    wg.Wait()
    fmt.Println(time.Now().Sub(before))
}

func setLimit() {
    var rLimit syscall.Rlimit
    if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil {
        panic(err)
    }
    rLimit.Cur = rLimit.Max
    if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit); err != nil {
        panic(err)
    }

    log.Printf("set cur limit: %d", rLimit.Cur)
}

running command

go run server.go
---
go run client.go

server running screenshot

enter image description here

The client simultaneously initiates 20,000 connections to the server, and the server accepted two remotePort connections that are exactly the same (in a extremely short period of time).

I try to use tcpconnect.py from bcc (patched to add skc_num)
enter image description here

tcpaccept.py
enter image description here
tracing the connection, and also finds that the remote port is duplicated on the server side when there is no duplicate on the client side

In my understanding, the 5-tuple of the socket will not be duplicated, Why the server accepted two sockets with exactly the same remote port?

My test environment:

kernel version 5.3.15-300.fc31.x86_64 and 4.19.1

go version go1.13.5 linux/amd64


Get this bounty!!!

#StackBounty: #go #kubernetes #kubernetes-apiserver #client-go Using client-go to `kubectl apply` against the Kubernetes API directly w…

Bounty: 50

I’m using https://github.com/kubernetes/client-go and all works well.

I have a manifest (YAML) for the official Kubernetes Dashboard: https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta4/aio/deploy/recommended.yaml

I want to mimic kubectl apply of this manifest in Go code, using client-go.

I understand that I need to do some (un)marshalling of the YAML bytes into the correct API types defined in package: https://github.com/kubernetes/api

I have successfully Createed single API types to my cluster, but how do I do this for a manifest that contains a list of types that are not the same? Is there a resource kind: List* that supports these different types?

My current work around is to split the YAML file using csplit with — as the delimiter

csplit /path/to/recommended.yaml /---/ '{*}' --prefix='dashboard.' --suffix-format='%03d.yaml'

Next, I loop over the new (14 parts) that were created, read their bytes, switch on the type of the object returned by the UniversalDeserializer’s decoder and call the correct API methods using my k8s clientset.

I would like to do this to programmatically to make updates to any new versions of the dashboard into my cluster. I will also need to do this for the Metrics Server and many other resources. The alternative (maybe simpler) method is to ship my code with kubectl installed to the container image and directly call kubectl apply -f -; but that means I also need to write the kube config to disk or maybe pass it inline so that kubectl can use it.

I found this issue to be helpful: https://github.com/kubernetes/client-go/issues/193
The decoder lives here: https://github.com/kubernetes/apimachinery/tree/master/pkg/runtime/serializer

It’s exposed in client-go here: https://github.com/kubernetes/client-go/blob/master/kubernetes/scheme/register.go#L69

I’ve also taken a look at the RunConvert method that is used by kubectl: https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/convert/convert.go#L139 and assume that I can provide my own genericclioptions.IOStreams to get the output?

It looks like RunConvert is on a deprecation path

I’ve also looked at other questions tagged [client-go] but most use old examples or use a YAML file with a single kind defined, and the API has changed since.

Edit: Because I need to do this for more than 1 cluster and are creating clusters programmatically (AWS EKS API + CloudFormation/eksctl), I would like to minimize the overhead of creating ServiceAccounts across many cluster contexts, across many AWS accounts. Ideally, the only authentication step involved in creating my clientset is using aws-iam-authenticator get a token using cluster data (name, region, CA cert, etc). There hasn’t been a release of aws-iam-authenticator for a while, but the contents of master allow for the use of a third-party role cross-account role and external ID to be passed. IMO this is cleaner than using a ServiceAccount (and IRSA) because there are other AWS services the application (the backend API which creates and applies add-ons to these clusters) needs to interact with.


Get this bounty!!!

#StackBounty: #go #circleci #alpine #bitbucket-cli CircleCI vs Bitbucket Go Build Issue

Bounty: 50

I’m running a go build command on a golang:1.11-alpine on two separate CI tools. As you can see the commands are exactly the same and the docker image is exactly the same.

For some reason, when I run the compiled executable on an alpine:3.9 docker image, only the bitbucket runs.

For the Circle CI build, I get the following error:

standard_init_linux.go:207: exec user process caused “exec format error”

I was reading online that it might be an architecture issue so I did a file <file> in the terminal and it appears both were compiled the same way. Here is the response I received for both files (identical):

cloud: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, stripped

Circle CI

docker:
  - image: golang:1.11-alpine

steps:
  - checkout
  - run:
      name: Build Go Server
      command: |
        apk add --no-cache git build-base
        export GOPATH="$HOME/go"
        export PATH="$PATH:$GOPATH/bin"
        go get -u github.com/golang/lint/golint@v0.0.0-20190227174305-8f45f776aaf1
        go mod vendor
        golint -set_exit_status $(go list ./... | grep -v /vendor/)
        go test -short $(go list ./... | grep -v /vendor/)
        go build -ldflags="-s -w"

Bitbucket CI

steps:
    - step: &step-test-and-build-go
            name: Test and Build Go Server
            image: golang:1.11-alpine
            script:
                - apk add --no-cache git build-base
                - export GOPATH="$HOME/go"
                - export PATH="$PATH:$GOPATH/bin"
                - go get -u github.com/golang/lint/golint@v0.0.0-20190227174305-8f45f776aaf1
                - go mod vendor
                - golint -set_exit_status $(go list ./... | grep -v /vendor/)
                - go test -short $(go list ./... | grep -v /vendor/)
                - go build -ldflags="-s -w"

Circle CI go env

GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/root/project/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build122963699=/tmp/go-build -gno-record-gcc-switches"

Bitbucket CI go env

GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/opt/atlassian/pipelines/agent/build/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build179086021=/tmp/go-build -gno-record-gcc-switches"

I have cross-posted this question to the CircleCI forum.


Get this bounty!!!

#StackBounty: #go Golang configuration management with viper package

Bounty: 50

I’m new to GO,

I created 2 different configuration resources. Also I created a manager responsible for initializing and reading the configurations and creating default ones if needed.

Is this a clean apporoach for handling configuration through the application? Would love to get some opinions and improvement suggestions. Thanks!

config_manager.go

package conf

import (
    config "github.com/spf13/viper"
    "log"
    "os"
    "sync"
)

var(
    usersConfig = config.New()
    dbConfig = config.New()
)

func InitAllConfigurations(){

    if _, err := os.Stat("data"); os.IsNotExist(err){
        err = os.MkdirAll("data", 0755)
        if err != nil {
            log.Fatal(err)
        }
    }

    var wg = sync.WaitGroup{}
    wg.Add(2)

    go func() {
        defer wg.Done()
        InitUsersConfiguration()
    }()

    go func() {
        defer wg.Done()
        InitDbConfiguration()
    }()

    wg.Wait()
}

db_config.go

package conf

import (
    "log"
    "os"
)

var DatabaseConfig databaseConfig

type databaseConfig struct {
    Name string `mapstructure:name`
    Type string    `mapstructure:type`
    Username string `mapstructure:username`
    Password string `mapstructure:password`
}

func InitDbConfiguration() {
    dbConfig.AddConfigPath("data/")
    dbConfig.SetConfigType("json")
    dbConfig.SetConfigName("database")

    if dbConfig.ReadInConfig() != nil {
        log.Print("Failed reading users config, setting default values")

        _, err := os.OpenFile("data/database.json", os.O_RDONLY|os.O_CREATE, 0666)

        if err != nil {
            log.Println(err)
        }

        dbConfig.SetDefault("db.name", "OutlookDB")
        dbConfig.SetDefault("db.type", "mongo")
        dbConfig.SetDefault("db.username", "username")
        dbConfig.SetDefault("db.password", "password")

        err = dbConfig.WriteConfig()

        if err != nil {
            log.Println(err)
        }
    }

    dbSection := dbConfig.Sub("db")
    err := dbSection.Unmarshal(&DatabaseConfig)

    if err != nil {
        log.Print(err)
    }
}

users_config.go

package conf

import (
    "log"
    "os"
)

var UserConfiguration userConfig


type User struct {
    Id int `mapstructure:id`
    Name string `mapstructure:name`
}

type userConfig struct {
    MyId     int    `mapstructure:my_id`
    AllUsers map[int]*User `mapstructure:all_users`
}

func InitUsersConfiguration() {
    usersConfig.AddConfigPath("data/")
    usersConfig.SetConfigType("json")
    usersConfig.SetConfigName("users")

    if usersConfig.ReadInConfig() != nil {
        log.Print("Failed reading users config, setting default values")

        os.OpenFile("data/users.json", os.O_RDONLY|os.O_CREATE, 0666)

        usersConfig.SetDefault("user.my_id", 1)
        usersConfig.SetDefault("user.all_users", map[int]User{
            1: {Id:1, Name:"First"},
            2: {Id:2, Name:"Second"},
            3: {Id:3, Name:"Third"},
        })

        err := usersConfig.WriteConfig()

        if err != nil {
            log.Print(err)
        }
    }

    userSection := usersConfig.Sub("user")
    err := userSection.Unmarshal(&UserConfiguration)

    if err != nil {
        log.Print(err)
    }
}

main.go

package main

import (
    "log"
    "outlook/conf"
)

func main(){
    conf.InitAllConfigurations()
    myUserName := conf.DatabaseConfig.Username
    log.Println(myUserName)

}


Get this bounty!!!

#StackBounty: #go #windows-subsystem-for-linux #ubuntu-18.04 #dep dep init -v hangs upon execution

Bounty: 50

I’ll start with a disclaimer here. I’m running go on Ubuntu 18.0.4 on Windows subsystem.

I have a package in which I was able to run “dep init” successfully from the windows command line. I created a new clone (successful clone, so no network connectivity issues) of the repo in my Ubuntu subsystem and ran “dep init.”

This is when I run into problems. Dep just hangs after pulling a single package down. Subsequent calls to dep init do not pull more packages. Running “dep init -v” produces the following:

#> dep init -v
Getting direct dependencies...
Checked 14 directories for packages.
Found 3 direct dependencies.

Take a look at the attached screen capture to see that process threads are spun up but are doing nothing (0% CPU and RAM usage).

Screen Capture with HTOP and my dep pkg folder structure

Things I’ve tried:

  1. Turning it off and on again.
  2. I’ve completely cleaned out my dep package folder and re-run dep init. This is how I know that there is just a single package that is actually getting pulled.
  3. Made sure that my ssh keys are up-to-date with github.


Get this bounty!!!

#StackBounty: #go #delve Go Delve (1.0.0-rc2) freezes on Windows after breakpoint hit

Bounty: 50

I have recently been having a problem which essentially makes debugging Go using delve next to impossible. Basically I can’t use breakpoints otherwise there is a good chance the debugged code freezes and all I can do is stop the debugger an restart.

To start at the beginning… I have had an intermittent problem debugging Go using GoLand IDE (2019.1) and delve (1.0.0-rc2) for some time. The whole session would freeze – I know that nothing is happening because the debugged process CPU usage is zero, and the fact that there are no messages being written to the log (I have many go-routines most of which are writing occasional log messages). It’s as if a breakpoint was hit but the debugger commands (STEP, etc) are not enabled which indicates that the debugger is not at a breakpoint. When this happens I have to hit the GoLand STOP button twice to get the debugger to terminate and then start all over again.

Recently this problem has become far more common. From perhaps a few times a day to almost every debug session. This is annoying but at least it has allowed me to track down what I believe is the underlying problem. It seems that sometimes when a breakpoint is encountered the debugger stops but delve or the IDE does not realise that – so there is no way to continue.

How do I know this? I proved this to myself by setting a breakpoint on a log line (ie, log.Printf). When the breakpoint is on that line (and I know it will be hit) then the debug session freezes. If I ensure there are no breakpoints that will be hit then the program runs absolutely fine including printing the log line. If I set the (one and only) breakpoint on the line after log line the log line is printed and the session freezes.

I think this is a problem with delve. Note that I have loaded the same project into VSCode and the exactly the same thing happens (GoLand and VSCode use the same version of delve), so I don’t think GoLand is doing anything wrong. But if someone has another explanation I welcome it.

I have tried a lot of things to track down the cause. I have created a small project in order to demonstrate the problem but it does not occur in a simple project. It appears that I am doing something wrong (in my large project) that causes delve to misbehave but I have no idea what that is.


Get this bounty!!!

#StackBounty: #tensorflow #go #deep-learning #recurrent-neural-network Tensorflow Partial Run on Golang (RNN states)

Bounty: 50

I have a GRU RNN text generation model that I imported as protobuf in Golang.

model, err := tf.LoadSavedModel("poetryModel", []string{"goTag"}, nil)

Similar to the code from this Tensorflow tutorial, I am running a prediction loop:

for len(generated_text) < 1000 {
    result, err := model.Session.Run(
            map[tf.Output]*tf.Tensor{
                model.Graph.Operation("inputLayer_input").Output(0): tensor,
            },
            []tf.Output{
                model.Graph.Operation("outputLayer/add").Output(0),
            },
            nil,
        )
    ...}

However, this implementation discards all intermediate states after every loop which results in bad generated text.
I tried using Partial Run, but it threw an error at the second Run:

pr, err := model.Session.NewPartialRun(
    []tf.Output{ model.Graph.Operation("inputLayer_input").Output(0), },
    []tf.Output{ model.Graph.Operation("outputLayer/add").Output(0), },
    []*tf.Operation{ model.Graph.Operation("outputLayer/add") },
)
if err != nil {
    panic(err)
}

...

result, err := pr.Run(
        map[tf.Output]*tf.Tensor{
            model.Graph.Operation("inputLayer_input").Output(0): tensor,
        },
        []tf.Output{
            model.Graph.Operation("outputLayer/add").Output(0),
        },
        nil,
    )

Error running the session with input, err: Must run 'setup' before performing partial runs!

This question is similar to this one, but in Python. Also, there is no documentation of a setup function in Go.
I am new to working directly with the TF computation graph and Golang, so any help is appreciated.


Get this bounty!!!

#StackBounty: #beginner #go #ascii-art Drawing a snowman in ASCII art

Bounty: 50

I am learning Go and as an exercise I did this challenge from Code Golf (without the golfing), where an ASCII art snowman is drawn from a combination of body parts, based on an 8-digit code taken as command line argument.

For example:

$ ./snowman 12431312

 _===_ 
 (-.O) 
<( : )
 ( : ) 

As a minor extension I decided to use a random code if none is passed.

Coming from Python, I had hoped to use the static typing to my advantage (e. g. by checking at compile time that the definition of body parts is valid), but I have the feeling that I am fighting it more than it helps me.

I’d like to know how I can make the code less verbose and repetitive, and how I can use the static typing to make the code less error-prone and brittle.

snowman.go

package main

import (
    "errors"
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "time"
)

type Snowman [5][7]rune

func (s Snowman) getLine(i int) string {
    var line string
    for _, c := range s[i] {
        line += string(c)
    }
    return line
}

func (s Snowman) String() string {
    var result string
    for i := range s {
        if i > 0 {
            result += "n"
        }
        result += s.getLine(i)
    }
    return result
}

type Hat [2][5]rune
type Nose rune
type Eye rune
type LeftArm [2]rune
type RightArm [2]rune
type Torso [3]rune
type Base [3]rune

var hats = [...]Hat{
    {{' ', ' ', ' ', ' ', ' '}, {'_', '=', '=', '=', '_'}},
    {{' ', '_', '_', '_', ' '}, {'.', '.', '.', '.', '.'}},
    {{' ', ' ', '_', ' ', ' '}, {' ', '/', '_', '\', ' '}},
    {{' ', '_', '_', '_', ' '}, {'(', '_', '*', '_', ')'}},
}

var noses = [...]Nose{',', '.', '_', ' '}

var eyes = [...]Eye{'.', 'o', 'O', '-'}

var leftArms = [...]LeftArm{{' ', '<'}, {'\', ' '}, {' ', '/'}, {' ', ' '}}

var rightArms = [...]RightArm{{' ', '>'}, {'/', ' '}, {' ', '\'}, {' ', ' '}}

var torsos = [...]Torso{
    {' ', ':', ' '},
    {']', ' ', '['},
    {'>', ' ', '<'},
    {' ', ' ', ' '},
}

var bases = [...]Base{
    {' ', ':', ' '},
    {'"', ' ', '"'},
    {'_', '_', '_'},
    {' ', ' ', ' '},
}

// newSnowman returns a Snowman with no hat, arms, face, torso, or base.
func newSnowman() Snowman {
    var s Snowman
    for _, i := range [3]int{0, 1, 4} {
        s[i][0] = ' '
        s[i][6] = ' '
    }
    for i := 2; i < 5; i++ {
        s[i][1] = '('
        s[i][5] = ')'
    }
    return s
}

func (s *Snowman) setHat(h Hat) {
    for i, line := range h {
        for j, c := range line {
            s[i][j+1] = c
        }
    }
}

func (s *Snowman) setNose(n Nose) {
    s[2][3] = rune(n)
}

func (s *Snowman) setLeftEye(e Eye) {
    s[2][2] = rune(e)
}

func (s *Snowman) setRightEye(e Eye) {
    s[2][4] = rune(e)
}

func (s *Snowman) setLeftArm(a LeftArm) {
    for i, c := range a {
        s[i+2][0] = c
    }
}

func (s *Snowman) setRightArm(a RightArm) {
    for i, c := range a {
        s[i+2][6] = c
    }
}

func (s *Snowman) setTorso(t Torso) {
    for i, c := range t {
        s[3][i+2] = c
    }
}

func (s *Snowman) setBase(b Base) {
    for i, c := range b {
        s[4][i+2] = c
    }
}

type SnowmanCode [8]int

func snowmanCodeFromString(s string) (SnowmanCode, error) {
    var result SnowmanCode
    if len(s) != 8 {
        return result, errors.New("expected 8 digits")
    }
    for i, digit := range s {
        num, err := strconv.Atoi(string(digit))
        if err != nil {
            return result, err
        }
        result[i] = num
    }
    return result, nil
}

func randomCode() SnowmanCode {
    return SnowmanCode{
        rand.Intn(len(hats)) + 1,
        rand.Intn(len(noses)) + 1,
        rand.Intn(len(eyes)) + 1,
        rand.Intn(len(eyes)) + 1,
        rand.Intn(len(leftArms)) + 1,
        rand.Intn(len(rightArms)) + 1,
        rand.Intn(len(torsos)) + 1,
        rand.Intn(len(bases)) + 1,
    }
}

func SnowmanFromCode(c SnowmanCode) (Snowman, error) {
    s := newSnowman()
    if !(1 <= c[0] && c[0] <= len(hats)) {
        return s, errors.New("hat code out of range")
    }
    if !(1 <= c[1] && c[1] <= len(noses)) {
        return s, errors.New("nose code out of range")
    }
    if !(1 <= c[2] && c[2] <= len(eyes)) {
        return s, errors.New("left eye code out of range")
    }
    if !(1 <= c[3] && c[3] <= len(eyes)) {
        return s, errors.New("right eye code out of range")
    }
    if !(1 <= c[4] && c[4] <= len(leftArms)) {
        return s, errors.New("left arm code out of range")
    }
    if !(1 <= c[5] && c[5] <= len(rightArms)) {
        return s, errors.New("right arm code out of range")
    }
    if !(1 <= c[6] && c[6] <= len(torsos)) {
        return s, errors.New("right arm code out of range")
    }
    if !(1 <= c[7] && c[7] <= len(bases)) {
        return s, errors.New("right arm code out of range")
    }
    s.setHat(hats[c[0]-1])
    s.setNose(noses[c[1]-1])
    s.setLeftEye(eyes[c[2]-1])
    s.setRightEye(eyes[c[3]-1])
    s.setLeftArm(leftArms[c[4]-1])
    s.setRightArm(rightArms[c[5]-1])
    s.setTorso(torsos[c[6]-1])
    s.setBase(bases[c[7]-1])
    return s, nil
}

func codeFromArgsOrRandom() (SnowmanCode, error) {
    if len(os.Args) > 1 {
        return snowmanCodeFromString(os.Args[1])
    } else {
        return randomCode(), nil
    }
}

func main() {
    rand.Seed(time.Now().UnixNano())
    code, err := codeFromArgsOrRandom()
    if err != nil {
        fmt.Println(err)
        return
    }
    s, err := SnowmanFromCode(code)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(s)
}


Get this bounty!!!

#StackBounty: #go #mocking #gomock resolving imported package collision for mockgen

Bounty: 50

I have a package collision where I get the following error:

mockgen -package=mocks -source=myproto.pb.go -destination=mocks/my_mocks.go
imported package collision: "foo" imported twice

I see one import that is obvious:
import foo "blah/blah/foo"

But I don’t know where to start tracking down the duplicate import (nor where it is coming from). It seems strange to me that this is an issue as I am importing myproto.pb.go just fine, so I’m wondering if there is really an issue w/duplicate imports. Also, GoLand isn’t showing any issues.

I’m hoping someone can point me in the direction of getting more information about where the duplicate import is coming form, checking if there is some issue and/or working around the issue.


Get this bounty!!!