首先大家知道golang是没有JAVA的泛型函数或者C++的模板函数这种语法的,今天学到了一种很有用的类似泛型操作的语法,拿来和大家分享

以大家喜闻乐见的Add函数来说明,目的是来实现一个泛型的Add函数

先写了三个ADD函数

package main

import (
	"fmt"
)

func Add1(a, b int) int {
	return a + b
}

func Add2(a, b float32) float32 {
	return a + b
}

func Add3(a, b string) string {
	return a + b
}

func main() {
	a1 := Add1(1, 2)
	a2 := Add2(1.33, 6.82)
	a3 := Add3("hello ", "world")
	fmt.Println("a1 =", a1, "a2 =", a2, "a3 =", a3)
}

在把三个ADD函数统一起来前,先学习一个简单的Interface{}的用法,注意int,int32,int64在setvalue的泛型判断中是不同的类型
package main

import (
	"fmt"
)

func SetValue(ret interface{}) {
	switch data := ret.(type) {
	case *float32:
		*data = 3.14
	case *int:
		*data = 23333
	case *int32:
		*data = 32
	case *int64:
		*data = 64
	default:
		fmt.Println("unknow type")
	}
}

func main() {
	var a1 int
	var a2 int32
	var a3 float32
	var a4 int64
	SetValue(&a1)
	SetValue(&a2)
	SetValue(&a3)
	SetValue(&a4)
	fmt.Println("a1 =", a1, "a2 =", a2, "a3 =", a3, "a4 =", a4)
}

相信到这里大部分同学都明白了,我们是要通过switch data:=input.(type)这样的类型判断来实现所谓的泛型,先按照最常规的
伪代码:Add(a,b){return a+b} 来实现
package main

import (
	"fmt"
)

func main() {
	a1 := Add1(1, 2)
	a2 := Add2(1.33, 6.82)
	a3 := Add3("hello ", "world")
	fmt.Println("a1 =", a1, "a2 =", a2, "a3 =", a3)

	b1 := GeneralAdd0(3, 5)
	switch data := b1.(type) {
	case int:
		fmt.Println("b1=", data)
	}
	b2 := GeneralAdd0(1.33, 6.82)
	switch data := b2.(type) {
	case float64:
		fmt.Println("b2=", data)
	}
	b3 := GeneralAdd0("hello ", "add0")
	switch data := b3.(type) {
	case string:
		fmt.Println("b3=", data)
	}
	fmt.Println("b1 =", b1, "b2 =", b2, "b3 =", b3)
}

func Add1(a, b int) int {
	return a + b
}

func Add2(a, b float32) float32 {
	return a + b
}

func Add3(a, b string) string {
	return a + b
}

func GeneralAdd0(a, b interface{}) interface{} {
	switch data := b.(type) {
	case float32:
		switch ta := a.(type) {
		case float32:
			data = data + ta
			return data
		}
	case float64:
		switch ta := a.(type) {
		case float64:
			data = data + ta
			return data
		}
	case int:
		switch ta := a.(type) {
		case int:
			data = data + ta
			return data
		}
	case string:
		switch ta := a.(type) {
		case string:
			data = data + ta
			return data
		}
	default:
		fmt.Println("unknow type")
		return nil
	}

	return nil
}

ps:这里b2其实是个float64类型

也可以传指针
package main

import (
	"fmt"
)

func main() {
	a1 := Add1(1, 2)
	a2 := Add2(1.33, 6.82)
	a3 := Add3("hello ", "world")
	fmt.Println("a1 =", a1, "a2 =", a2, "a3 =", a3)

	b1 := GeneralAdd0(3, 5)
	switch data := b1.(type) {
	case int:
		fmt.Println("b1=", data)
	}
	b2 := GeneralAdd0(1.33, 6.82)
	switch data := b2.(type) {
	case float64:
		fmt.Println("b2=", data)
	}
	b3 := GeneralAdd0("hello ", "add0")
	switch data := b3.(type) {
	case string:
		fmt.Println("b3=", data)
	}
	fmt.Println("b1 =", b1, "b2 =", b2, "b3 =", b3)

	var c1, cret1 int = 10, 42
	GeneralAdd1(&c1, &cret1)
	var c2, cret2 float32 = 5.11, 6.22
	GeneralAdd1(&c2, &cret2)
	var c3, cret3 string = "add1", "I am "
	GeneralAdd1(&c3, &cret3)
	fmt.Println("cret1 =", cret1, "cret2 =", cret2, "cret3 =", cret3)
}

func Add1(a, b int) int {
	return a + b
}

func Add2(a, b float32) float32 {
	return a + b
}

func Add3(a, b string) string {
	return a + b
}

func GeneralAdd0(a, b interface{}) interface{} {
	switch data := b.(type) {
	case float32:
		switch ta := a.(type) {
		case float32:
			data = data + ta
			return data
		}
	case float64:
		switch ta := a.(type) {
		case float64:
			data = data + ta
			return data
		}
	case int:
		switch ta := a.(type) {
		case int:
			data = data + ta
			return data
		}
	case string:
		switch ta := a.(type) {
		case string:
			data = data + ta
			return data
		}
	default:
		fmt.Println("unknow type")
		return nil
	}

	return nil
}

func GeneralAdd1(a, ret interface{}) {
	switch data := ret.(type) {
	case *float32:
		switch ta := a.(type) {
		case *float32:
			*data = *data + *ta
		}
	case *int:
		switch ta := a.(type) {
		case *int:
			*data = *data + *ta
		}
	case *string:
		switch ta := a.(type) {
		case *string:
			*data = *data + *ta
		}
	default:
		fmt.Println("unknow type")
	}
}
看到这里有没有想到一个问题,如果我的add函数是 伪代码:add(a,b,c){return a+b+c},难道我要switch case嵌套3次?这样的代码看着也太难受了
因此自定义的数据类型也是可以判断的哦

package main

import (
	"fmt"
)

func main() {
	a1 := Add1(1, 2)
	a2 := Add2(1.33, 6.82)
	a3 := Add3("hello ", "world")
	fmt.Println("a1 =", a1, "a2 =", a2, "a3 =", a3)

	b1 := GeneralAdd0(3, 5)
	switch data := b1.(type) {
	case int:
		fmt.Println("b1=", data)
	}
	b2 := GeneralAdd0(1.33, 6.82)
	switch data := b2.(type) {
	case float64:
		fmt.Println("b2=", data)
	}
	b3 := GeneralAdd0("hello ", "add0")
	switch data := b3.(type) {
	case string:
		fmt.Println("b3=", data)
	}
	fmt.Println("b1 =", b1, "b2 =", b2, "b3 =", b3)

	var c1, cret1 int = 10, 42
	GeneralAdd1(&c1, &cret1)
	var c2, cret2 float32 = 5.11, 6.22
	GeneralAdd1(&c2, &cret2)
	var c3, cret3 string = "add1", "I am "
	GeneralAdd1(&c3, &cret3)
	fmt.Println("cret1 =", cret1, "cret2 =", cret2, "cret3 =", cret3)

	d1 := IntStruct{a: 9, b: 45, ret: 0}
	GeneralAdd2(&d1)
	d2 := Float32Struct{a: 4.77, b: 7.99, ret: 0.0}
	GeneralAdd2(&d2)
	d3 := StringStruct{a: "I am", b: "stringstruct", ret: ""}
	GeneralAdd2(&d3)
	fmt.Println("d1 =", d1.ret, "d2 =", d2.ret, "d3 =", d3.ret)
}

func Add1(a, b int) int {
	return a + b
}

func Add2(a, b float32) float32 {
	return a + b
}

func Add3(a, b string) string {
	return a + b
}

func GeneralAdd0(a, b interface{}) interface{} {
	switch data := b.(type) {
	case float32:
		switch ta := a.(type) {
		case float32:
			data = data + ta
			return data
		}
	case float64:
		switch ta := a.(type) {
		case float64:
			data = data + ta
			return data
		}
	case int:
		switch ta := a.(type) {
		case int:
			data = data + ta
			return data
		}
	case string:
		switch ta := a.(type) {
		case string:
			data = data + ta
			return data
		}
	default:
		fmt.Println("unknow type")
		return nil
	}

	return nil
}

func GeneralAdd1(a, ret interface{}) {
	switch data := ret.(type) {
	case *float32:
		switch ta := a.(type) {
		case *float32:
			*data = *data + *ta
		}
	case *int:
		switch ta := a.(type) {
		case *int:
			*data = *data + *ta
		}
	case *string:
		switch ta := a.(type) {
		case *string:
			*data = *data + *ta
		}
	default:
		fmt.Println("unknow type")
	}
}

type Float32Struct struct {
	a   float32
	b   float32
	ret float32
}

type IntStruct struct {
	a   int
	b   int
	ret int
}

type StringStruct struct {
	a   string
	b   string
	ret string
}

func GeneralAdd2(ret interface{}) {
	switch data := ret.(type) {
	case *Float32Struct:
		data.ret = data.a + data.b
	case *IntStruct:
		data.ret = data.a + data.b
	case *StringStruct:
		data.ret = data.a + data.b
	default:
		fmt.Println("unknow type")
	}
}