Learning GO and I wrote this for a programming challenge. It is working (building and running) but I feel the code is not what GO code should be :

- am I using the
`struct`

element correctly ? especially struct methods ?
- in the
`playTurn()`

method, I reassign results (else not taken into account) because scope. How to write it better ? Pointer ?
- I am struggling with
`int`

, `float64`

and casting all the time. What’s the good practice in this context were I need float for precision in-between but inputs and outputs are int ?

full script :

`package main import ( "fmt" "math" "os" "strconv" ) // Pod is life type Pod struct { position Dot vx, vy, angle, nextCpID int hasShieldOn bool } func squaredDist(a, b Dot) int { return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) } func distance(a, b Dot) float64 { return math.Sqrt(float64(squaredDist(a, b))) } func (pod Pod) getAngle(p Dot) float64 { d := distance(p, pod.position) dx := float64(p.x-pod.position.x) / d dy := float64(p.y-pod.position.y) / d a := math.Acos(dx) * 180.0 / math.Pi // If the point I want is below me, I have to shift the angle for it to be correct if dy < 0 { a = 360.0 - a } return a } func (pod Pod) diffAngle(p Dot) float64 { a := pod.getAngle(p) pangle := float64(pod.angle) right := 0.0 if pangle <= a { right = a - pangle } else { right = 360.0 - pangle + a } left := 0.0 if pangle >= a { left = pangle - a } else { left = pangle + 360.0 - a } if right < left { return right } return -left } func (pod Pod) rotate(p Dot) int { a := pod.diffAngle(p) // Can't turn more than 18° in one turn ! if a > 18.0 { a = 18.0 } else if a < -18.0 { a = -18.0 } pod.angle += int(math.Round(a)) if pod.angle >= 360.0 { pod.angle = pod.angle - 360.0 } else if pod.angle < 0.0 { pod.angle += 360.0 } return pod.angle } func (pod Pod) boost(t int) (int, int) { if pod.hasShieldOn { return pod.vx, pod.vy } pangle := float64(pod.angle) pod.vx += int(math.Round(math.Cos(pangle) * float64(t))) pod.vy += int(math.Round(math.Sin(pangle) * float64(t))) return pod.vx, pod.vy } // t shoud become a float later on func (pod Pod) move(t int) (int, int) { pod.position.x += pod.vx * t pod.position.y += pod.vy * t return pod.position.x, pod.position.y } func (pod Pod) endTurn() (int, int) { // todo rounding position if needed pod.vx = int(float64(pod.vx) * 0.85) pod.vy = int(float64(pod.vy) * 0.85) return pod.vx, pod.vy } func (pod Pod) playTurn(p Dot, t int) { pod.angle = pod.rotate(p) pod.vx, pod.vy = pod.boost(t) pod.position.x, pod.position.y = pod.move(1) pod.vx, pod.vy = pod.endTurn() fmt.Fprintf(os.Stderr, "\nPredicted Pod position : ") fmt.Fprintf(os.Stderr, "\n(%d, %d) speed (%d,%d)", pod.position.x, pod.position.y, pod.vx, pod.vy) } // Dot is king type Dot struct { x, y int } func main() { var laps int fmt.Scan(&laps) var checkpointCount int fmt.Scan(&checkpointCount) var checkPoints []Dot for i := 0; i < checkpointCount; i++ { var checkpointX, checkpointY int fmt.Scan(&checkpointX, &checkpointY) checkPoints = append(checkPoints, Dot{checkpointX, checkpointY}) } var myPods [2]Pod var itsPods [2]Pod for { for i := 0; i < 2; i++ { // x: x position of your pod // y: y position of your pod // vx: x speed of your pod // vy: y speed of your pod // angle: angle of your pod // nextCheckPointId: next check point id of your pod var x, y, vx, vy, angle, nextCheckPointID int fmt.Scan(&x, &y, &vx, &vy, &angle, &nextCheckPointID) myPods[i] = Pod{Dot{x, y}, vx, vy, angle, nextCheckPointID, false} fmt.Fprintf(os.Stderr, "\nActual Pod position : ") fmt.Fprintf(os.Stderr, "\n(%d, %d) speed (%d,%d)", myPods[i].position.x, myPods[i].position.y, myPods[i].vx, myPods[i].vy) } for i := 0; i < 2; i++ { // x2: x position of the opponent's pod // y2: y position of the opponent's pod // vx2: x speed of the opponent's pod // vy2: y speed of the opponent's pod // angle2: angle of the opponent's pod // nextCheckPointId2: next check point id of the opponent's pod var x2, y2, vx2, vy2, angle2, nextCheckPointID2 int fmt.Scan(&x2, &y2, &vx2, &vy2, &angle2, &nextCheckPointID2) itsPods[i] = Pod{Dot{x2, y2}, vx2, vy2, angle2, nextCheckPointID2, false} } // fmt.Fprintln(os.Stderr, "Debug messages...") for _, pod := range myPods { nx := checkPoints[pod.nextCpID].x - 3*pod.vx ny := checkPoints[pod.nextCpID].y - 3*pod.vy // Predicting where my pods will be next turn: pod.playTurn(Dot{nx, ny}, 100) // fmt.Println(strconv.Itoa(nx) + " " + strconv.Itoa(ny) + " 100") } } } `