Fix: Go cannot use X (type Y) as type Z in argument
Quick Answer
How to fix Go 'cannot use as type' error caused by type mismatches, interface satisfaction, pointer vs value receivers, type conversions, and generic constraints.
The Error
You compile Go code and get:
cannot use myVar (variable of type string) as int value in argument to processNumberOr variations:
cannot use &myStruct (value of type *MyStruct) as MyInterface value in variable declaration:
*MyStruct does not implement MyInterface (missing method DoSomething)cannot use mySlice (variable of type []int) as []interface{} value in argumentcannot use 42 (untyped int constant) as string value in return statementcannot use myFunc (value of type func(int)) as func(interface{}) valueGo’s type system is strict. You passed a value of one type where a different type is expected, and Go does not implicitly convert between them.
Why This Happens
Go has no implicit type conversions. Unlike JavaScript or Python, Go does not automatically convert an int to a string, a []int to []interface{}, or a float64 to an int. You must convert explicitly.
Additionally, Go interfaces are satisfied structurally (no explicit implements keyword), but the satisfaction rules are strict about pointer vs value receivers.
Common causes:
- Wrong argument type. Passing a
stringwhere anintis expected. - Missing interface method. A type does not implement all methods of an interface.
- Pointer vs value receiver mismatch. A method is defined on
*Tbut you passT(not a pointer). - Slice type mismatch.
[]intis not[]interface{}even thoughintsatisfiesinterface{}. - Named type vs underlying type.
type MyInt intis a different type fromint.
Fix 1: Use Explicit Type Conversion
Go requires explicit conversions between compatible types:
var x int = 42
var y float64 = float64(x) // int → float64
var z string = strconv.Itoa(x) // int → string (not string(x)!)
var f float64 = 3.14
var i int = int(f) // float64 → int (truncates decimal)
var s string = "hello"
var b []byte = []byte(s) // string → []byte
var s2 string = string(b) // []byte → stringCommon mistake — string(int):
s := string(65) // "A" — converts int to Unicode codepoint, NOT "65"!
s := strconv.Itoa(65) // "65" — converts int to its string representationPro Tip: Use
strconvfor numeric ↔ string conversions.string(n)interpretsnas a Unicode codepoint, which is almost never what you want.strconv.Itoa(n)converts the number to its decimal string representation.
Fix 2: Fix Interface Satisfaction
If the error says a type does not implement an interface:
type Writer interface {
Write(data []byte) (int, error)
}
type MyWriter struct{}
func (w MyWriter) Write(data string) error { // Wrong signature!
return nil
}
var w Writer = MyWriter{}
// cannot use MyWriter{} as Writer value: MyWriter does not implement Writer
// (wrong type for method Write)The method signature must exactly match the interface method:
func (w MyWriter) Write(data []byte) (int, error) {
fmt.Print(string(data))
return len(data), nil
}Parameter types, return types, and the number of parameters must all match exactly.
Fix 3: Fix Pointer vs Value Receiver
Methods defined on *T (pointer receiver) are only available to pointer values when satisfying interfaces:
Broken:
type Stringer interface {
String() string
}
type User struct {
Name string
}
func (u *User) String() string { // Pointer receiver
return u.Name
}
var s Stringer = User{Name: "Alice"} // ERROR!
// cannot use User{} as Stringer value: User does not implement Stringer
// (method String has pointer receiver)Fixed — use a pointer:
var s Stringer = &User{Name: "Alice"} // Pointer — works!Or use a value receiver:
func (u User) String() string { // Value receiver
return u.Name
}
var s Stringer = User{Name: "Alice"} // Works — value receiver
var s Stringer = &User{Name: "Alice"} // Also works — pointer can use value receiversRule of thumb:
| Receiver | Value satisfies interface? | Pointer satisfies interface? |
|---|---|---|
func (t T) | Yes | Yes |
func (t *T) | No | Yes |
Common Mistake: Defining methods with pointer receivers but trying to store values (not pointers) in interface variables. If any method uses a pointer receiver, you must use a pointer to satisfy the interface. Consistency helps — use either all pointer receivers or all value receivers for a type.
Fix 4: Fix Slice Type Mismatches
Go slices are not covariant. []int is not []interface{} even though int satisfies interface{}:
Broken:
func printAll(items []interface{}) {
for _, item := range items {
fmt.Println(item)
}
}
numbers := []int{1, 2, 3}
printAll(numbers)
// cannot use numbers (variable of type []int) as []interface{} valueFixed — use generics (Go 1.18+):
func printAll[T any](items []T) {
for _, item := range items {
fmt.Println(item)
}
}
numbers := []int{1, 2, 3}
printAll(numbers) // Works!Fixed — convert manually:
numbers := []int{1, 2, 3}
items := make([]interface{}, len(numbers))
for i, n := range numbers {
items[i] = n
}
printAll(items)Why this limitation exists: In Go, []int and []interface{} have different memory layouts. An int is stored directly in the slice element; an interface{} stores a type descriptor and a pointer. Go cannot reinterpret the memory, so an explicit conversion is required.
Fix 5: Fix Named Type Conversions
Named types are distinct from their underlying types:
type UserID int
type OrderID int
func processUser(id UserID) {}
var orderID OrderID = 42
processUser(orderID)
// cannot use orderID (variable of type OrderID) as UserID valueFix: Convert explicitly:
processUser(UserID(orderID))Named types with the same underlying type can be converted between each other, but Go does not do it implicitly. This is a feature — it prevents mixing up IDs of different entity types.
Fix 6: Fix Function Type Mismatches
Function types must match exactly:
type Handler func(w http.ResponseWriter, r *http.Request)
func myHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello"))
}
var h Handler = myHandler // Works — exact match
// But:
type GenericHandler func(interface{})
func specificHandler(s string) {}
var g GenericHandler = specificHandler
// cannot use specificHandler as GenericHandler valueFix with adapters:
var g GenericHandler = func(v interface{}) {
specificHandler(v.(string))
}Fix 7: Fix Map Type Mismatches
Like slices, maps are not covariant:
func process(m map[string]interface{}) {}
data := map[string]int{"a": 1, "b": 2}
process(data)
// cannot use data as map[string]interface{} valueFixed — use generics:
func process[V any](m map[string]V) {}
data := map[string]int{"a": 1, "b": 2}
process(data) // Works!Fixed — convert manually:
converted := make(map[string]interface{}, len(data))
for k, v := range data {
converted[k] = v
}
process(converted)Fix 8: Fix Error Interface Returns
A common confusion with the error interface:
type MyError struct {
Message string
}
func (e *MyError) Error() string {
return e.Message
}
func doSomething() error {
var err *MyError = nil
return err // Returns a non-nil interface containing a nil pointer!
}
if err := doSomething(); err != nil {
// This is TRUE even though the underlying pointer is nil!
fmt.Println("Error:", err)
}Fixed — return nil directly:
func doSomething() error {
// ...
return nil // Return nil, not a typed nil pointer
}This is a notorious Go gotcha. An interface is only nil when both its type and value are nil. A nil *MyError stored in an error interface has a non-nil type, so err != nil is true.
For related Go issues with unused variables, see Fix: Go declared and not used.
Still Not Working?
Check for generic constraints. In Go 1.18+, generic type parameters must satisfy their constraints:
func sum[T int | float64](values []T) T { ... }
sum([]string{"a", "b"}) // string does not satisfy int | float64Check for type assertions. If you need to work with interface{} values, use type assertions:
var v interface{} = "hello"
s := v.(string) // Type assertion — panics if wrong type
s, ok := v.(string) // Safe assertion — ok is false if wrong typeCheck for struct embedding. Embedded structs can satisfy interfaces through promoted methods, but only if the method signatures match exactly.
Use the compiler’s suggestion. Go’s error messages often include the expected and actual types. Compare them carefully — the difference might be subtle (pointer vs value, named vs unnamed type, different package paths for the same type name).
For Go module issues that prevent compilation, see Fix: Go module not found.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Go cannot find package / no required module provides package
How to fix 'cannot find package' and 'no required module provides package' errors in Go by syncing dependencies, fixing import paths, configuring private repos, and resolving workspace issues.
Fix: Go fatal error: all goroutines are asleep - deadlock!
How to fix Go fatal error all goroutines are asleep deadlock caused by unbuffered channels, missing goroutines, WaitGroup misuse, and channel direction errors.
Fix: Go panic: runtime error: index out of range
How to fix Go panic runtime error index out of range caused by empty slices, off-by-one errors, nil slices, concurrent access, and missing bounds checks.
Fix: Go undefined: variable (or function)
How to fix Go undefined error caused by undeclared variables, wrong package scope, unexported names, missing imports, build tags, and file organization issues.