泛型的基本使用

  我们先来看两个自定义函数

package main

// InSliceInt 检查int切片中是否存在某个值
func InSliceInt(needle int, haystack []int) bool {
   for _, value := range haystack {
      if value == needle {
         return true
      }
   }

   return false
}

// InSliceString 检查string切片中是否存在某个值
func InSliceString(needle string, haystack []string) bool {
   for _, value := range haystack {
      if value == needle {
         return true
      }
   }

   return false
}

  两个自定义函数的功能都是检查切片中是否存在某个值,函数体代码也是完全一致的,唯一不同的就是形参的数据类型,仅仅因为形参的数据类型不同开发者就要写两个函数体代码完全一致的自定义函数,很明显这样的代码没有通用性,而使用泛型则可以使代码更具通用性。

package main

import "fmt"

// InSlice 检查切片中是否存在某个值
// 重要说明①:“[T int | string]”表示定义一个名为T(注:名称可随便起)的泛型,其数据类型可以是int,也可以是string。
// 重要说明②:“needle T”表示形参needle的数据类型为泛型T,即形参needle的数据类型可以是int,也可以是string。
// 重要说明③:“haystack []T”表示形参haystack的数据类型为泛型T切片,即切片元素的数据类型可以是int,也可以是string。
func InSlice[T int | string](needle T, haystack []T) bool {
   for _, value := range haystack {
      if value == needle {
         return true
      }
   }

   return false
}

func main() {
   sliceInt := []int{9, 5, 2, 7}
   sliceString := []string{"张三", "李四", "王五"}

   num1 := 1
   if InSlice(num1, sliceInt) {
      fmt.Printf("%+v%+v\n", num1, sliceInt)
   } else {
      fmt.Printf("%+v 不在 %+v\n", num1, sliceInt) // 1 不在 [9 5 2 7] 里
   }

   num2 := 2
   if InSlice(num2, sliceInt) {
      fmt.Printf("%+v%+v\n", num2, sliceInt) // 2 在 [9 5 2 7] 里
   } else {
      fmt.Printf("%+v 不在 %+v\n", num2, sliceInt)
   }

   str1 := "赵六"
   if InSlice(str1, sliceString) {
      fmt.Printf("%+v%+v\n", str1, sliceString)
   } else {
      fmt.Printf("%+v 不在 %+v\n", str1, sliceString) // 赵六 不在 [张三 李四 王五] 里
   }

   str2 := "张三"
   if InSlice(str2, sliceString) {
      fmt.Printf("%+v%+v\n", str2, sliceString) // 张三 在 [张三 李四 王五] 里
   } else {
      fmt.Printf("%+v 不在 %+v\n", str2, sliceString)
   }
}

  泛型可以理解为一种约束,如果形参的数据类型声明为泛型,那么入参值的数据类型只能是该泛型限定的数据类型的其中一种。泛型限定的数据类型不仅可以是int、string等基本数类型,还可以是结构体类型。

Copyright © 2024 码农人生. All Rights Reserved