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

  • removeDuplicateElementThe function initializes two variables, one of length 0slice, an emptymap. Due to thesliceParameters are passed by reference and no additional memory space is created.
  • map[string]struct{}{}Creates a key of type String and value of type nullstructthemapIs equivalent to usingmake(map[string]struct{})
  • emptystructIt 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