others-how to solve 'cannot use value.ID (type uint) as type uint64 in argument to strconv.FormatUint' when running golang program ?
Problem
When we run a golang ( or go) progam as follows:
go run main.go
sometimes , we get this error:
models/book.go:37:30: cannot use value.ID (type uint) as type uint64 in argument to strconv.FormatUint
Why do this error happen? The golang program is correct, I promise!!!
Environment
- go version go 1.14+
The code
The main code of the program is:
package main
import (
"errors"
"fmt"
"strconv"
)
type Book struct {
ID uint
Title string
Author string
}
var Books []Book
func init() {
Books = []Book {
Book{
ID: 1,
Title: "halibote测试",
Author: "mam",
},
Book{
ID: 2,
Title: "jifeigoutiao",
Author: "an",
},
}
}
func FindABook(bookId string)(Book,error) {
defaultResult := Book{}
for _,value:=range Books {
if strconv.FormatUint(value.ID,10)==bookId {
return value,nil
}
}
return defaultResult,errors.New("not found "+bookId)
}
func main() {
book, err := FindABook("3")
if err == nil {
fmt.Printf(" got book %v\n", book)
}else {
fmt.Printf("%v\n",err)
}
}
Reason
Our Book’s ID’s type is uint, it can not be converted to uint64, which is required by strconv.FormatUint.
This is the definition of the strconv.FormatUint:
func FormatUint(i uint64, base int) string
FormatUint returns the string representation of i in the given base, for 2 <= base <= 36. The result uses the lower-case letters ‘a’ to ‘z’ for digit values >= 10.
Solution #1
We should change the type of Book.ID before the string conversion:
func FindABook(bookId string)(Book,error) {
defaultResult := Book{}
for _,value:=range Books {
if strconv.FormatUint(uint64(value.ID),10)==bookId {
return value,nil
}
}
return defaultResult,errors.New("not found "+bookId)
}
The key point is :
if strconv.FormatUint(uint64(value.ID),10)==bookId {
We use uint64() to convert uint to uint64.
Solution #2
We can also change our Book’s definition like this:
type Book struct {
ID uint64
Title string
Author string
}
Then we convert it to string like this:
if strconv.FormatUint(value.ID,10)==bookId {
Solution #3
We can still use the uint type, and try to convert it to string using fmt.Sprint as follows:
type Book struct {
ID uint
Title string
Author string
}
...
func FindABook(bookId string)(Book,error) {
defaultResult := Book{}
for _,value:=range Books {
if idstring := fmt.Sprint(value.ID); idstring==bookId {
return value,nil
}
}
return defaultResult,errors.New("not found "+bookId)
}
Here we use the fmt.Sprint function to convert the uint type to string, let’s check the definition of fmt.Sprint:
In Go language, fmt package implements formatted I/O with functions analogous to C’s printf() and scanf() function. The fmt.Sprint() function in Go language formats using the default formats for its operands and returns the resulting string.
Run the app again, No error messages ,It works!
By the way
The basic types of integer in golang:
int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr
The int, uint, and uintptr types are usually 32 bits wide on 32-bit systems and 64 bits wide on 64-bit systems. When you need an integer value you should use int unless you have a specific reason to use a sized or unsigned integer type.