difference between declaring variables with var vs without var in go - go

I was having some trouble with step 35 in the tour of Go exercise.
Here's what my code looks like:
package main
import "code.google.com/p/go-tour/pic"
func Pic(dx, dy int) [][]uint8 {
var pic = make([][]uint8, dy)
for y := 0; y < dy; y++ {
pic[y] = make([]uint8, dx)
for x := 0; y < dx; x++ {
pic[y][x] = uint8(x*y)
}
}
return pic
}
When looking for a solution, I found PeterSO's code which works perfectly
func main() {
pic.Show(Pic)
}
func Pic(dx, dy int) [][]uint8 {
pixels := make([][]uint8, dy)
for y := 0; y < dy; y++ {
pixels[y] = make([]uint8, dx)
for x := 0; x < dx; x++ {
pixels[y][x] = uint8(x * y)
}
}
return pixels
}
The only difference I can see, is that I'm defining the pic variable using the var keyword whereas his code is using the := assignment. Now, why does my code not work?

You wrote
for x := 0; y < dx; x++ {
pic[y][x] = uint8(x * y)
}
in particular: y < dx, which causes,
panic: runtime error: index out of range
I wrote
for x := 0; x < dx; x++ {
pixels[y][x] = uint8(x * y)
}
in particular: x < dx. Therefore, change your y to x.
package main
import "code.google.com/p/go-tour/pic"
func Pic(dx, dy int) [][]uint8 {
var pic = make([][]uint8, dy)
for y :=0; y < dy; y++ {
pic[y] = make([]uint8, dx)
for x :=0; x<dx; x++ {
pic[y][x] = uint8(x*y)
}
}
return pic
}
func main() {
pic.Show(Pic)
}
http://play.golang.org/p/UvGgszFhl-
Variable declarations
A variable declaration creates a variable, binds an identifier to it
and gives it a type and optionally an initial value.
VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
Short variable declarations
A short variable declaration uses the syntax:
ShortVarDecl = IdentifierList ":=" ExpressionList .
It is a shorthand for a regular variable declaration with initializer
expressions but no types:
"var" IdentifierList = ExpressionList .
Unlike regular variable declarations, a short variable declaration may
redeclare variables provided they were originally declared earlier in
the same block with the same type, and at least one of the non-blank
variables is new.
In your code var pic = make([][]uint8, dy) and the short form pic := make([][]uint8, dy) will both work.

If you use the :=, the type of the variable is implied from the expression on the right of the sign. If you use =, no assumption is made and you need to specify the type yourself.
In this case, you should write it like this:
var pic [][]uint8 = make([][]uint8, dy)
but this is indeed better because shorter and as clear:
pic := make([][]uint8, dy)

Related

how declare two variables in for init in GoLang? [duplicate]

This question already has answers here:
Can you declare multiple variables at once in Go?
(8 answers)
Closed 5 years ago.
when i write:
package main
import (
"fmt"
)
func Sqrt(x float64) float64 {
var ret float64
for z := 1.0, n := 0;n < 10;n++ {
ret = z - (z*z - x) / 2*z
}
return ret
}
func main() {
fmt.Println(Sqrt(2))
}
syntax error: z := 1.0, n used as value.
and bring
z := 1.0
out of the for block below
package main
import (
"fmt"
)
func Sqrt(x float64) float64 {
var ret float64
z := 1.0
for n := 0;n < 10;n++ {
ret = z - (z*z - x) / 2*z
}
return ret
}
func main() {
fmt.Println(Sqrt(2))
}
it's ok so how can i define two variables in init of the for block?
A For clause has an Init Statement which is a Simple Statement, including only one Assigment
So in your case, you cannot declare multiple variable with different type/values. You could use a tuple assignment though
for z, n := 1.0, 0; n < 10; n++ {
(playground)

Go tour #18. How do I pass in integers to Pic?

The following code errors with index out of range. I tried modifying main to
pic.Show(Pic(500, 500)) but that changes the argument from function to the return type and it fails to compile. How do I pass in integers if the pic.Show is expecting a function as an argument.
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int) [][]uint8 {
mypic := [][]uint8{}
for y := 0; y < dy; y++ {
mypic[y] = []uint8{}
for x := 0; x < dx; x++ {
mypic[y][x] = uint8((x + y) / 2)
}
}
return mypic
}
func main() {
pic.Show(Pic)
}
You don't. The Go Tour program will pass Pic test values to your program. Your problem is in your code: panic: runtime error: index out of range. [][]uint8{} and []uint8{} allocate zero y and zero x slice elements. Use make to allocate your y and x slices. For example,
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int) [][]uint8 {
pixels := make([][]uint8, dy)
for y := 0; y < dy; y++ {
pixels[y] = make([]uint8, dx)
for x := 0; x < dx; x++ {
pixels[y][x] = uint8((x + y) / 2)
}
}
return pixels
}
func main() {
pic.Show(Pic)
}
Reference: Making slices, maps and channels, The Go Programming Language Specification

Golang exercise slices how does it deal with big values

I'm going through the Golang tutorial and I'm a little bit confused as to what it is doing with some of the values in the slices exercise. https://tour.golang.org/moretypes/18
Here is the code that I am confused with:
A value of 0 is a perfectly blue pixel and a value of 255 is a perfectly white pixel. So what is happening here when the value displayed is some form of x*y (I did /20 to make the image a little bit bigger and easier to see).
If you follow the image horizontally, you will see that at some point in the process, the ever increasing x and y values seem to revert to blue (0 value) If I type a static value like 256 in the return I get a compile error. So it obviously does not allow the numbers to go off the scale and revert to 0 or anything. So how does it get the blue curves in the picture?
imported source here: https://github.com/golang/tour/blob/master/pic/pic.go#L15
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int) [][]uint8 {
//First, the array has to be made so we can put some values in it later
//This only makes the second dimension of the array ([[uint8 dy]])?
image := make([][]uint8, dy)
//The inputs into the function are Int's, so it is ok to have a non uint8
//loop initializer
for x := 0; x < dy; x++ {
//once we are in the loop we have to make the first dimension of the array
//based on the dx values
image[x] = make([]uint8, dx)
for y := 0; y < dx; y++ {
//This is a function +to assign the pixel values to the array
image[x][y] = uint8((x * y) /20)
}
}
return image
}
func main() {
pic.Show(Pic)
}
Imagine i is of type int, uint8(i) returns Least Significant Byte (LSB) of i:
When x is in range [0, 255] , meaning: 0 <= x <= 255
and y is in range [0, 255],
then x*y is in range [0, 255*255] = [0, 65025]
so x*y/20 is in range [0, 255*255/20] = [0, 65025/20] = [0, 3251]
and value of uint8(x*y/20) is equal to (x*y/20)%256 meaning exactly LSB byte:
uint8(3251) = uint8(0XCB3) = 0XB3 = 179
3251 = 12*256 + 179
So every time the x*y/20 is bigger than 255 it counts from 0 again: (x*y/20) % 256 this is why your image is repeated circles.
Try this working sample code:
package main
import "fmt"
func main() {
for y := 0; y <= 255; y++ {
for x := 0; x <= 255; x++ {
v := x * y / 20
if int(uint8(v)) != v%256 {
fmt.Println(v, v%256)
}
}
}
fmt.Println("Done.")
}
output:
Done.
Let's simplify you example, see this working sample code:
package main
import (
"bytes"
"image"
"image/png"
"os"
)
func main() {
const dx = 256
const dy = 256
m := image.NewNRGBA(image.Rect(0, 0, dx, dy))
for y := 0; y < dy; y++ {
for x := 0; x < dx; x++ {
v := uint8(x * y / 20)
i := y*m.Stride + x*4
m.Pix[i] = v //R
m.Pix[i+1] = v //G
m.Pix[i+2] = 255 //B
m.Pix[i+3] = 255 //A
}
}
var buf bytes.Buffer
err := png.Encode(&buf, m)
if err != nil {
panic(err)
}
os.Stdout.Write(buf.Bytes())
}
And redirect the output to a file like main > b.png or, go run main.go > b.png
see output file b.png:
uint8(anotherIntValue) conversion will take the last byte of anotherIntValue. That is why your code can produce many blue (0). For example, following code would print 'val = 0'.
dx, dy := 128, 2
fmt.Println("val =", uint8(dx*dy))
Constant conversion will be checked by compiler for out of range errors.

Go language: Type XXX is not an expression

I have written a function:
func Pic(dx, dy int) [][]uint8 {
type matrix [][]uint8
for i := 0; i < dx; i++ { // fills up the matrix with z's in their right places.
for j := 0; j < dy; j++ {
matrix[i][j] = Z(i,j)
}
}
return matrix
}
that is supposed to fill up a matrix with z values for each x and y value and return it. As I want to have different dimensions for the matrix depending of parameters to the Pic function, I create a slice i line 2. Then in my for loops i fill the matrix up.
I get an error upon running this code: type matrix is not an expression for the matrix[i][j] = Z(i,j) line. What am I doing wrong? Should matrix[i][j] evaluate to an expression? Why should it, when I want to put something there (it's empty/non-existent now!) ?
You're declaring matrix as a type, but using it as a variable.
try:
var matrix [][]uint8
While you can use var matrix [][]uint8, I'd recommend using the built-in make function since you know the desired lengths—dx for the outer slice and dy for the inner slice. The Two-dimensional slices section of Effective Go gives an example of using make to allocate a two-dimensional slice. Below is an example for your Pic function.
func Pic(dx, dy int) [][]uint8 {
matrix := make([][]uint8, dx)
for i := 0; i < dx; i++ {
matrix[i] = make([]uint8, dy)
for j := 0; j < dy; j++ {
matrix[i][j] = Z(i, j)
}
}
return matrix
}

"declared and not used" Error

I get this error saying that I'm not using a variable… but to my noob eyes, it looks like I am:
func Sqrt(x float64) float64 {
z := float64(x);
for i := 0; i < 10; i++ {
z := z - (z*z - x) / (2 * z);
}
return z;
}
Can anyone point out what I'm missing about the language? I think it has to do with = vs. := and scoping, but I'm not sure.
The := in your for-loop declares a new variable z which shadows the outer z. Turn it into a plain = to fix the problem.
func Sqrt(x float64) float64 {
z := x
for i := 0; i < 10; i++ {
z = z - (z*z - x) / (2 * z);
}
return z;
}
By the way, for equal precision and a bit more speed you could try the following implementation which does two of your steps at once:
func Sqrt(x float64) float64 {
z := x
for i := 0; i < 5; i++ {
a := z + x/z
z = a/4 + x/a
}
return z
}
Here is another way to look at the function
func Sqrt(x float64) (z float64) {
z = x
for i := 0; i < 10; i++ {
z = z - (z*z - x)/(2*z);
}
return
}

Resources