Go의 형식에 얽매이지 않는 좋은 느낌의 Contains 함수로 쓰는 방법

18059 단어 Go리플렉스tech

개시하다


Go의 표준 패키지에는 슬라이스와 배열에 특정 값이 포함되어 있는지 판단하는 Contains 함수가 존재하지 않기 때문에 자작합니다.
JavaScript의 Arayincludes 방법과 Python의 in 연산자와 유사한 기능인상은 다음과 같다.
// int型のスライス
containsInt := Contains([]int{1, 2, 3, 4, 5}, 3)
fmt.Println(containsInt) // -> true
// string型のスライス
containsString := Contains([]string{"apple", "orange", "lemon"}, "orange")
fmt.Println(containsString) // -> true
// 構造体のスライス
type hero struct {
    Name string
}
heros := []hero{hero{"Luke"}, hero{"Han"}, hero{"Leia"}}
containsStruct := Contains(heros, hero{"Han"})
fmt.Println(containsStruct) // -> true

Contains에 대한 고정 설치 없음


Stack OverflowContains method for a slice에서 Go의 Contains 함수에 대해 열띤 토론을 벌였지만 다수의 실시례는 특정 유형에 맞추어 전문적으로 실시되었다.
// int型専用のContains関数
func Contains(s []int, e int) bool {
    for _, a := range s {
        if a == e {
            return true
        }
    }
    return false
}
스트라이프 형식에 얽매이지 않고 어떤 종류(int,flat64,string,구조체)도 사용할 수 있는 함수의 설치 예시가 의외로 없습니다.

Contains 함수 구현


특정 유형의 속박을 받지 않고 int,flat64 등 원시형에서 구조체로의 슬라이드를 덮어쓰는 Contains 함수의 실현은 다음과 같다.
func Contains(list interface{}, elem interface{}) bool {
    listV := reflect.ValueOf(list)

    if listV.Kind() == reflect.Slice {
        for i := 0; i < listV.Len(); i++ {
            item := listV.Index(i).Interface()
	    // 型変換可能か確認する
	    if !reflect.TypeOf(elem).ConvertibleTo(reflect.TypeOf(item)) {
	        continue
            }
            // 型変換する
            target := reflect.ValueOf(elem)
	        .Convert(reflect.TypeOf(item)).Interface()
	    // 等価判定をする
            if ok := reflect.DeepEqual(item, target); ok {
                return true
            }
        }
    }
    return false
}
반사경을 사용하여 슬라이드를 조작하면서 슬라이드의 구성원을 Reflect한다.Value.요점은 Convert 함수를 사용하여 객체 값을 읽어들이는 유형으로 변환하는 것입니다.
reflect.Value.Convert 메서드는 변환하기 전에 유형 변환이 실패할 때 패닉이 발생합니다.Type.유형 변환이 가능한지 확인하려면 ConvertibleTo 메서드를 사용합니다.
당초 컨버티블투 방법을 쓰지 않고 패닉이 생기기 쉬운 시행 방식을 적용했으나 선생님 지도하에 패닉이 발생하지 않도록 수정했다.이 자리를 빌려 감사 드립니다.

Contains 함수 사용 방법


사용 방법은 다음과 같다.첫 번째 매개변수에 슬라이스를 입력하고 두 번째 매개변수에 객체 찾기 값을 지정합니다.int32와flat32 등 Go의 원시적인 절단부터 구조체의 절단까지 대응할 수 있다.
// int32のスライス
containsInt32 := Contains([]int32{1, 2, 3, 4, 5}, 3)
fmt.Println(containsInt32) // -> true
// intのスライス
containsInt := Contains([]int{1, 2, 3, 4, 5}, 2)
fmt.Println(containsInt) // -> true
// float64のスライス
containsFloat64 := Contains([]float64{1.1, 2.2, 3.3, 4.4, 5.5}, 4.4)
fmt.Println(containsFloat64) // -> true
// string型のスライス
containsString := Contains([]string{"apple", "orange", "lemon"}, "orange")
fmt.Println(containsString) // -> true
// 構造体のスライス
type item struct {
    ID   string
    Name string
}
list := []item{
    item{
        ID:   "1",
        Name: "test1",
    },
    item{
        ID:   "2",
        Name: "test2",
    },
    item{
        ID:   "3",
        Name: "test3",
    },
}
target := item{
	ID:   "2",
	Name: "test2",
}
containsStruct := Contains(list, target)
fmt.Println(containsStruct) // -> true

총결산

  • Contains 함수는 사용하는 장면이 많지만 고정된 실현이 없다
  • 반사를 사용하여 원시 유형에서 구조체로의Contains 함수를 만들 수 있음
  • 반사를 사용하기 때문에 특정 유형의 설치에 비해 실행 속도가 느려진다
  • 앞으로 Go에 Generix를 설치하면 이렇게 할 필요가 없기 때문에 그 전에 이 함수로 극복하고 싶습니다.본고에서 소개한 함수는 여기.에 설치되어 있으니 단원 테스트를 참고하십시오.

    참고 자료

  • Contains method for a slice
  • glassonion1/xgo
  • 좋은 웹페이지 즐겨찾기