Any idiomatic way to code in go

Hey Thanks for taking look at the thread.

I try to use golang to practice interview, but I found my code look verbose, don’t think it is go-style, is there any idea or way to refactoring code to improve the quality of code since I am not read enough good code though

Since I know this can be a really big topic, I attached the code I wrote which look ugly.

Thanks again for any help or suggestion.:joy:

type Item struct {
    s string
    v float64
}

func calcEquation(equations [][]string, values []float64, queries [][]string) []float64 {
    m := make(map[string]map[string]float64)
    var res []float64
    // base on equations to generate graph
    for i, v := range equations {
        // check subMap is present or not
        if tempM, ok:= m[v[0]]; ok {
            tempM[v[1]] = values[i]
        } else {
            tempM := make(map[string]float64)
            tempM[v[1]] = values[i]
            m[v[0]] = tempM
        }
        if tempm, ok := m[v[1]]; ok {
            tempm[v[0]] = 1.0/values[i]
        } else {
            tempm := make(map[string]float64)
            tempm[v[0]] = 1.0 / values[i]
            m[v[1]] = tempm
        }
    }
    for k, v := range queries {
        // Any good looking way to handle specific multi-keys check in map 
        if _, ok := m[v[0]]; !ok {
            res = append(res, -1.0)
            continue
        }
        if _, ok := m[v[1]]; !ok {
            res = append(res, -1.0)
            continue
        }
        if v[0] == v[1] {
            res = append(res, 1.0)
            continue
        }
        q := []Item{}
        q = append(q, Item{v[0], 1.0})
        visited := make(map[string]bool)
        // BFS Traversal
        for len(q) != 0 {
            var pop Item
            pop, q =  q[len(q)-1], q[:len(q)-1]
            if visited[pop.s] {
                continue
            }
            visited[pop.s] = true
            for sKey, value:= range m[pop.s] {
                if sKey == v[1] {
                    res = append(res, pop.v * value)
                    break 
                }
                q = append(q, Item{sKey, pop.v*value})
            }
        }
        if len(res) < k+1 {
            res = append(res, -1.0)
        }    
    }
    return res
}
tempM[v[1]] = values[i] 
m[v[0]] = tempM

Can be shortened as

mapm[v[0]] = map[string]float64{v[1]: values[i]}
1 Like

The various if; continue blocks can be replaced with a switch statement.

Thanks Dave, I assume you refer here:

// Any good looking way to handle specific multi-keys check in map 
        if _, ok := m[v[0]]; !ok {
            res = append(res, -1.0)
            continue
        }
        if _, ok := m[v[1]]; !ok {
            res = append(res, -1.0)
            continue
        }
        if v[0] == v[1] {
            res = append(res, 1.0)
            continue
        }

I try to rewrite the code:

func calcEquation(equations [][]string, values []float64, queries [][]string) []float64 {
    m := make(map[string]map[string]float64)
    var res []float64
    for i, v := range equations {
        if tempM, ok:= m[v[0]]; ok {
            // when key present, set it!
            tempM[v[1]] = values[i]
        } else {
            // key is absent, initialize map value, populate value
            m[v[0]] = map[string]float64{v[1]: values[i]}
        }
        if tempm, ok := m[v[1]]; ok {
            tempm[v[0]] = 1.0/values[i]
        } else {
            m[v[1]] = map[string]float64{v[0]: 1.0/values[i]}
        }
    }
    for k, v := range queries {
        // check elments in slice v are not the key in graph map, if not: break
		for _, el := range v {
			if _, ok := m[el]; !ok {
				res = append(res, -1.0)
				break
			}
		}
        // check if it coming from break case, then continue to next round 
        if len(res) == k+1 {
            continue
        }
        if v[0] == v[1] {
            res = append(res, 1.0)
            continue
        }
        q := []Item{}
        q = append(q, Item{v[0], 1.0})
        visited := make(map[string]bool)
        for len(q) != 0 {
            var pop Item
            pop, q =  q[len(q)-1], q[:len(q)-1]
            if visited[pop.s] {
                continue
            }
            visited[pop.s] = true
            fmt.Println(m[pop.s]["6"])
            for sKey, value:= range m[pop.s] {
                if sKey == v[1] {
                    res = append(res, pop.v * value)
                    break 
                }
                q = append(q, Item{sKey, pop.v*value})
            }
        }
        if len(res) < k+1 {
            res = append(res, -1.0)
        }    
    }
    return res
}

what I want to do is check elements in slices v, are not key in m if not, will continue to next round loop, after rework code, I found my code still not good, like spaghetti code, any idea on that?
On first section, is that the idiomatic way to handle cases where key present in map?

Thanks again for help. BTW: I read a lot of your blog posts, lovin’t it.:wink:

Something like this

        switch {
        case len(es) == k+1: 
             // nothing to do
        case v[0] == v[1]:
            res = append(res, 1.0)
        default:
        q := []Item{}
        ...

And so on

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.