Type converting slices of interfaces in Go: a complete breakdown with examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: why "type converting slices of interfaces" is a pain for every Go developer

\n\n

If you've ever written Go code that accepts []interface{} and tried to convert it to []string or []int, you've likely encountered this annoying compiler message: cannot convert []interface{} to []string. This is one of the most popular problems on Stack Overflow, with thousands of views. And it's no surprise — at first glance, logic suggests: "If each element is an interface{} that stores a string, why can't I just convert the entire slice?"

\n\n

The answer lies in how Go works with types and memory. Type converting slices of interfaces is not just type casting, but a full data copy. In this article, we'll break down the problem from top to bottom: starting with theory, going through practical examples, and ending with ready-made solutions you can immediately use in your projects.

\n\n

By the way, if you write in Go and work with undefined data types — for example, when parsing JSON or processing data from external sources — this topic is critically important for you. Let's go!

\n\n

Why doesn't Go allow directly converting []interface{} to []T?

\n\n

Let's start with a fundamental understanding. In Go, interface{} is a special type that stores a pair: (type, value). When you have []interface{}, each element occupies a different number of bytes in memory (depending on the stored type). And []string is a contiguous array of string structures (each string is a pointer to data + length).

\n\n

Imagine you have a box with multi-colored balls of different sizes (that's []interface{}), and you need to move them into a box where all balls are the same color and size ([]string). You can't just move the box — you need to check each ball, take it out, and put it into a new box. That's exactly what happens during type converting slices of interfaces.

\n\n

Key point: type assertion only works with individual elements, not with the entire slice as a whole. Go does not provide syntactic sugar for mass conversion — this is done intentionally so that you explicitly control what happens to each element.

\n\n

Example of an error you've likely seen

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    data := []interface{}{"apple", "banana", "cherry"}\n    // Compilation error:\n    // cannot use data (variable of type []interface{}) as type []string in assignment\n    // var fruits []string = data\n    fmt.Println(data)\n}\n
\n\n

This code will not compile. The Go compiler is strict about types, and implicit conversion of slices of different types is prohibited. Even if you are sure that only strings are inside.

\n\n

The correct way: Type Assertion for each element

\n\n

The simplest and most understandable way to perform type converting slices of interfaces is to iterate over each element in a loop and apply type assertion.

\n\n

Basic example with type assertion

\n\n
package main\n\nimport "fmt"\n\nfunc convertToStrings(data []interface{}) []string {\n    result := make([]string, 0, len(data))\n    for _, v := range data {\n        // Attempt to assert that v is a string\n        if str, ok := v.(string); ok {\n            result = append(result, str)\n        } else {\n            // Error handling: element is not a string\n            fmt.Printf("Warning: element %v is not a string, skipping\\n", v)\n        }\n    }\n    return result\n}\n\nfunc main() {\n    mixed := []interface{}{"hello", 42, "world", true, "golang"}\n    strings := convertToStrings(mixed)\n    fmt.Println(strings) /                

Blogs

Book Recommendations