3

I recently tried to learn golang. But I got confused with this code from https://tour.golang.org/basics/13.

package main

import (
    "fmt"
    "math"
)

func main() {
    var x, y int = 3, 4
    var f float64 = math.Sqrt(float64(x*x + y*y))
    var z uint = uint(f)
    fmt.Println(x, y, z)
}

That one works well. Then I tried

var f = math.Sqrt(9 + 16)

which also works. But when I change it to var f = math.Sqrt(x*x + y*y) why is it not working? It says cannot use x * x + y * y (type int) as type float64 in argument to math.Sqrt

I have javascript background, and I somehow can't understand the code above.

muhajirframe
  • 61
  • 1
  • 7
  • Related / possible duplicate of [Sleeping by Fractions of a Time Duration](https://stackoverflow.com/questions/42605412/sleeping-by-fractions-of-a-time-duration/42606191#42606191). – icza Jul 06 '17 at 20:20

2 Answers2

7

The math.Sqrt function signature:

func Sqrt(x float64) float64

requires that you pass float64

In this case:

var f float64 = math.Sqrt(float64(x*x + y*y))

You are converting to float64 directly

In this case:

var f = math.Sqrt(x*x + y*y)

you are passing an int, when float64 is required.

In this case:

var f = math.Sqrt(9 + 16)

The compiler is able to infer the type, and pass float64 for you.

Akavall
  • 82,592
  • 51
  • 207
  • 251
  • So when pass a variable which has value a number, the compiler doesn't convert it automatically? But when we pass a number directly, it automatically converted? – muhajirframe Jul 06 '17 at 04:56
  • @muhajir, basically yes, when you pass in a variable, `x` and `y` that were explicitly declared as `int`, which is not a `float64`, so the compiler rejects that. When you pass in a number directly, the compiler checks the function signatures and sees if the input is valid for a `float64` and it is, much like this is valid: `var x float64 = 4` – Akavall Jul 06 '17 at 05:11
4

But when we pass a number directly, it automatically converted?

No, not really *). Your "direct numbers" are called "constants" in Go and constants are often "untyped" and (almost) of arbitrary precision. There are special rules for constants: A constant 5 and the integer a defined by a := 5 behave differently because 5 is a constant with special rules and not an int.

Constant expressions like 9 + 16 are evaluated at compile time like if you had typed 25. This 25 is still a (constant.

While Go does not have automatic type conversions for types it does have automatic conversions from constants to several types. The constant 25 can be converted to float64 or int, uint8 or even complex128 automatically.

Please read the blog post https://blog.golang.org/constants and the official language spec for a full explanation and all details: https://golang.org/ref/spec#Constants . This explains the strange notion of "untyped integer" better than I could.

*) "not really" because it is not helpful to think about it that way. The distinction of constants is special in Go: Most other languages tread 3+5 as a sum of two ints resulting in an int while Go sees two untyped integer constants and evaluates this expression into a new arbitrary precision, untyped constant. Only later are constants converted to actual integers.

Volker
  • 40,468
  • 7
  • 81
  • 87