The Go library itself does not provide a function to remove duplicate elements from slice; you need to implement it yourself. The following provides a kind of implementation idea, if there is a better implementation method welcome to leave a message to discuss.
package main
import (
"fmt"
)
func main() {
s := []string{"hello"."world"."hello"."golang"."hello"."ruby"."php"."java"}
fmt.Println(removeDuplicateElement(s)) //output: hello world golang ruby php java
}
func removeDuplicateElement(languages []string) []string {
result := make([]string, 0, len(languages))
temp := map[string]struct{}{}
for _, item := range languages {
if_, ok := temp[item]; ! ok { temp[item] = struct{}{} result = append(result, item) } }return result
}
Copy the code
explain
removeDuplicateElement
The function initializes two variables, one of length 0slice
, an emptymap
. Due to theslice
Parameters are passed by reference and no additional memory space is created.map[string]struct{}{}
Creates a key of type String and value of type nullstruct
themap
Is equivalent to usingmake(map[string]struct{})
- empty
struct
It doesn’t take up memory space, and using it to implement our function space is minimal.
Playground URL Reference URL
Suitable for multiple slice types
The function above, which removes duplicate elements, can only handle string slices but not other types of slices. If you don’t want to write a deduplication function for every type of slice, you can use Go’s type-switch to write a function that can handle multiple slice types. Here’s an implementation I wrote:
package common
import (
"fmt"
)
type sliceError struct {
msg string
}
func (e *sliceError) Error() string {
returne.msg } func Errorf(format string, args ... interface{}) error { msg := fmt.Sprintf(format, args...)
return &sliceError{msg}
}
func removeDuplicateElement1(originals interface{}) (interface{}, error) {
temp := map[string]struct{}{}
switch slice := originals.(type) {
case []string:
result := make([]string, 0, len(originals.([]string)))
for _, item := range slice {
key := fmt.Sprint(item)
if_, ok := temp[key]; ! ok { temp[key] = struct{}{} result = append(result, item) } }return result, nil
case []int64:
result := make([]int64, 0, len(originals.([]int64)))
for _, item := range slice {
key := fmt.Sprint(item)
if_, ok := temp[key]; ! ok { temp[key] = struct{}{} result = append(result, item) } }return result, nil
default:
err := Errorf("Unknown type: %T", slice)
return nil, err
}
}
Copy the code
-
The function takes an argument of an empty interface type and uses the type selection to enter the appropriate branch for processing. This is where you can add the type of slice handlers that the function needs to support.
-
Each branch also creates a map with a key of type string and an empty struct. The value of key is the String representation of the sliced element (the return value of the String() method of type)
-
The type of the return value of the function is an empty interface, so it can only be used after receiving the return value with a type assertion.
The original link