Understanding the Error
Go is a statically typed language. When types don't match, you'll see errors like:
./main.go:10:15: cannot use myVar (type int) as type string
./main.go:15:22: cannot use user (type *User) as type User
./main.go:20:8: cannot use data (type interface{}) as type string: need type assertion
./main.go:25:10: cannot use s (type MyString) as type Stringer: MyString does not implement Stringer (missing String method)Common Scenarios and Solutions
Scenario 1: Basic Type Conversion
Problem code:
``go
func main() {
var age int = 25
var message string = "Age is " + age // Error: cannot use age (type int) as type string
fmt.Println(message)
}
Solution - Explicit conversion:
``go
func main() {
var age int = 25
var message string = "Age is " + strconv.Itoa(age)
fmt.Println(message)
}
Common conversions: ```go // Int to string s := strconv.Itoa(42) s := fmt.Sprintf("%d", 42)
// String to int n, err := strconv.Atoi("42")
// Float to int n := int(3.14) // n = 3
// Int to float f := float64(42)
// Byte slice to string s := string([]byte{72, 101, 108, 108, 111})
// String to byte slice b := []byte("Hello") ```
Scenario 2: Pointer vs Value Type
Problem code: ```go type User struct { Name string }
func processUser(u User) { fmt.Println(u.Name) }
func main() { user := &User{Name: "Alice"} processUser(user) // Error: cannot use user (type *User) as type User } ```
Solution 1 - Dereference the pointer:
``go
processUser(*user) // Pass a copy
Solution 2 - Modify function to accept pointer: ```go func processUser(u *User) { fmt.Println(u.Name) }
processUser(user) // Works ```
Solution 3 - Make function accept either: ```go func processUser(u User) { fmt.Println(u.Name) }
func main() { user := &User{Name: "Alice"} processUser(*user) // Dereference when calling // Or directUser := User{Name: "Bob"} processUser(directUser) } ```
Scenario 3: Interface Type Assertion
Problem code:
``go
func main() {
var i interface{} = "hello"
var s string = i // Error: cannot use i (type interface{}) as type string
fmt.Println(s)
}
Solution - Type assertion: ```go func main() { var i interface{} = "hello"
// Unsafe assertion (panics if wrong type) s := i.(string) fmt.Println(s)
// Safe assertion with comma-ok idiom s, ok := i.(string) if ok { fmt.Println(s) } else { fmt.Println("Not a string") } } ```
Type switch for multiple types:
``go
func describe(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Integer: %d\n", v)
case string:
fmt.Printf("String: %s\n", v)
case bool:
fmt.Printf("Boolean: %t\n", v)
default:
fmt.Printf("Unknown type: %T\n", v)
}
}
Scenario 4: Interface Implementation
Problem code: ```go type Writer interface { Write([]byte) (int, error) }
type MyWriter struct{}
func (w *MyWriter) Write(data []byte) (int, error) { return len(data), nil }
func useWriter(w Writer) {}
func main() { mw := MyWriter{} useWriter(mw) // Error: cannot use mw (type MyWriter) as type Writer } ```
Why this fails:
The Write method is defined on *MyWriter, not MyWriter. So only *MyWriter implements Writer.
Solution 1 - Pass pointer:
``go
func main() {
mw := &MyWriter{}
useWriter(mw) // Works
}
Solution 2 - Define method on value: ```go func (w MyWriter) Write(data []byte) (int, error) { return len(data), nil }
func main() { mw := MyWriter{} useWriter(mw) // Now works } ```
Scenario 5: Custom Type Confusion
Problem code: ```go type ID int type UserID ID type ProductID ID
func getUser(id UserID) {}
func main() { var uid UserID = 1 var pid ProductID = 2
getUser(pid) // Error: cannot use pid (type ProductID) as type UserID } ```
Solution - Explicit conversion: ```go func main() { var uid UserID = 1 var pid ProductID = 2
getUser(uid) // Works getUser(UserID(pid)) // Explicit conversion } ```
Better design - use struct with type safety: ```go type UserID struct{ value int } type ProductID struct{ value int }
func NewUserID(v int) UserID { return UserID{value: v} } func (id UserID) Value() int { return id.value } ```
Scenario 6: Slice/Array Type Mismatch
Problem code:
``go
func main() {
var slice []int = []int{1, 2, 3}
var array [3]int = slice // Error: cannot use slice (type []int) as type [3]int
}
Solution - Copy elements: ```go func main() { slice := []int{1, 2, 3} array := [3]int{} copy(array[:], slice)
// Or use direct assignment array := [3]int{slice[0], slice[1], slice[2]} } ```
Generic Type Constraints (Go 1.18+)
Problem code: ```go func Sum[T int | float64](values []T) T { var total T for _, v := range values { total += v } return total }
func main() { Sum([]string{"a", "b"}) // Error: string does not satisfy int | float64 } ```
Solution - Use appropriate types:
``go
func main() {
Sum([]int{1, 2, 3}) // Works
Sum([]float64{1.1, 2.2}) // Works
}
Or expand the constraint: ```go type Number interface { int | int64 | float32 | float64 }
func Sum[T Number](values []T) T { var total T for _, v := range values { total += v } return total } ```
Debugging Type Issues
Use fmt.Printf with %T
func main() {
var i interface{} = "hello"
fmt.Printf("Type: %T, Value: %v\n", i, i)
// Output: Type: string, Value: hello
}Use reflect Package
```go import "reflect"
func main() { var x interface{} = []int{1, 2, 3}
fmt.Println("Type:", reflect.TypeOf(x)) fmt.Println("Kind:", reflect.TypeOf(x).Kind()) fmt.Println("Value:", reflect.ValueOf(x))
// Check if type implements an interface t := reflect.TypeOf(x) writerType := reflect.TypeOf((*Writer)(nil)).Elem() fmt.Println("Implements Writer:", t.Implements(writerType)) } ```
Compile-Time Interface Check
var _ Writer = (*MyWriter)(nil) // Compile error if *MyWriter doesn't implement WriterVerification
```bash # Check types at compile time go build ./...
# Use go vet for common type issues go vet ./...
# Use staticcheck for deeper analysis go install honnef.co/go/tools/cmd/staticcheck@latest staticcheck ./... ```