Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting a compile error 'cannot use ... as type uint8 in argument to ...' when the parameter is an int

Tags:

go

I am new to Go and was working through a problem in The Go Programming Language. The code should create GIF animations out of random Lissajous figures with the images being produced in the different colors from palate:

// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/

// Run with "web" command-line argument for web server.
// See page 13.
//!+main

// Lissajous generates GIF animations of random Lissajous figures.
package main

import (
    "image"
    "image/color"
    "image/gif"
    "io"
    "math"
    "math/rand"
    "os"
)

//!-main
// Packages not needed by version in book.
import (
    "log"
    "net/http"
    "time"
)

//!+main
// #00ff55
var palette = []color.Color{color.RGBA{0x00, 0xff, 0x55, 0xFF}, color.Black, color.RGBA{0x00, 0x00, 0xff, 0xFF}, color.RGBA{0xff, 0x00, 0xff, 0xFF}}

const (
    whiteIndex = 0 // first color in palette
)

func main() {
    //!-main
    // The sequence of images is deterministic unless we seed
    // the pseudo-random number generator using the current time.
    // Thanks to Randall McPherson for pointing out the omission.
    rand.Seed(time.Now().UTC().UnixNano())

    if len(os.Args) > 1 && os.Args[1] == "web" {
        //!+http
        handler := func(w http.ResponseWriter, r *http.Request) {
            lissajous(w)
        }
        http.HandleFunc("/", handler)
        //!-http
        log.Fatal(http.ListenAndServe("localhost:8000", nil))
        return
    }
    //!+main
    lissajous(os.Stdout)
}

func lissajous(out io.Writer) {
    const (
        cycles  = 5     // number of complete x oscillator revolutions
        res     = 0.001 // angular resolution
        size    = 100   // image canvas covers [-size..+size]
        nframes = 64    // number of animation frames
        delay   = 8     // delay between frames in 10ms units
    )
    freq := rand.Float64() * 3.0 // relative frequency of y oscillator
    anim := gif.GIF{LoopCount: nframes}
    phase := 0.0 // phase difference
  colorIndex := 2
  for i := 0; i < nframes; i++ {
    rect := image.Rect(0, 0, 2*size+1, 2*size+1)
        img := image.NewPaletted(rect, palette)
        for t := 0.0; t < cycles*2*math.Pi; t += res {
            x := math.Sin(t)
            y := math.Sin(t*freq + phase)
      img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), colorIndex)
      colorIndex++
        }
        phase += 0.1
        anim.Delay = append(anim.Delay, delay)
        anim.Image = append(anim.Image, img)
    }
    gif.EncodeAll(out, &anim) // NOTE: ignoring encoding errors
}

//!-main

Here is the error I am getting

lissajous/main.go:76: cannot use colorIndex (type int) as type uint8 in argument to img.SetColorIndex

Is there a difference between int and uint8 types or something?

like image 710
nomel7 Avatar asked Dec 17 '16 18:12

nomel7


2 Answers

The type of colorIndex is int. The argument type is uint8. An int cannot be assigned to a uint8. Here are some options for fixing the program:

  • Declare colorIndex as an untyped constant.

    const colorIndex = 2
    
  • Declare colorIndex as uint8 type:

    colorIndex := uint8(3)
    
  • Convert the value at the call:

    img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), uint8(colorIndex))
    

You can replace all uses of uint8 in this answer with byte because byte is an alias for uint8.

like image 190
Bayta Darell Avatar answered Oct 12 '22 09:10

Bayta Darell


In variable declarations, a default type is used, and in your case, colorIndex := 2, i.e. colorIndex becomes int, not uint8.

From the docs ( https://golang.org/ref/spec#Short_variable_declarations ): "If a type is present, each variable is given that type. Otherwise, each variable is given the type of the corresponding initialization value in the assignment. If that value is an untyped constant, it is first converted to its default type;..."

"var i = 42 // i is int"

and then

"An untyped constant has a default type which is the type to which the constant is implicitly converted in contexts where a typed value is required, for instance, in a short variable declaration such as i := 0 where there is no explicit type. The default type of an untyped constant is bool, rune, int, float64, complex128 or string respectively, depending on whether it is a boolean, rune, integer, floating-point, complex, or string constant."

So to get uint8, you should either explicitly declare colorIndex as uint8 var colorIndex uint8 = 2 or cast uint8 in img.SetColorIndex as : img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), uint8(colorIndex))

like image 45
oharlem Avatar answered Oct 12 '22 09:10

oharlem