github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/types/testdata/examples/functions.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file shows some examples of type-parameterized functions. 6 7 package p 8 9 // Reverse is a generic function that takes a []T argument and 10 // reverses that slice in place. 11 func Reverse[T any](list []T) { 12 i := 0 13 j := len(list)-1 14 for i < j { 15 list[i], list[j] = list[j], list[i] 16 i++ 17 j-- 18 } 19 } 20 21 func _() { 22 // Reverse can be called with an explicit type argument. 23 Reverse[int](nil) 24 Reverse[string]([]string{"foo", "bar"}) 25 Reverse[struct{x, y int}]([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}}) 26 27 // Since the type parameter is used for an incoming argument, 28 // it can be inferred from the provided argument's type. 29 Reverse([]string{"foo", "bar"}) 30 Reverse([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}}) 31 32 // But the incoming argument must have a type, even if it's a 33 // default type. An untyped nil won't work. 34 // Reverse(nil) // this won't type-check 35 36 // A typed nil will work, though. 37 Reverse([]int(nil)) 38 } 39 40 // Certain functions, such as the built-in `new` could be written using 41 // type parameters. 42 func new[T any]() *T { 43 var x T 44 return &x 45 } 46 47 // When calling our own `new`, we need to pass the type parameter 48 // explicitly since there is no (value) argument from which the 49 // result type could be inferred. We don't try to infer the 50 // result type from the assignment to keep things simple and 51 // easy to understand. 52 var _ = new[int]() 53 var _ *float64 = new[float64]() // the result type is indeed *float64 54 55 // A function may have multiple type parameters, of course. 56 func foo[A, B, C any](a A, b []B, c *C) B { 57 // do something here 58 return b[0] 59 } 60 61 // As before, we can pass type parameters explicitly. 62 var s = foo[int, string, float64](1, []string{"first"}, new[float64]()) 63 64 // Or we can use type inference. 65 var _ float64 = foo(42, []float64{1.0}, &s) 66 67 // Type inference works in a straight-forward manner even 68 // for variadic functions. 69 func variadic[A, B any](A, B, ...B) int { panic(0) } 70 71 // var _ = variadic(1) // ERROR "not enough arguments" 72 var _ = variadic(1, 2.3) 73 var _ = variadic(1, 2.3, 3.4, 4.5) 74 var _ = variadic[int, float64](1, 2.3, 3.4, 4) 75 76 // Type inference also works in recursive function calls where 77 // the inferred type is the type parameter of the caller. 78 func f1[T any](x T) { 79 f1(x) 80 } 81 82 func f2a[T any](x, y T) { 83 f2a(x, y) 84 } 85 86 func f2b[T any](x, y T) { 87 f2b(y, x) 88 } 89 90 func g2a[P, Q any](x P, y Q) { 91 g2a(x, y) 92 } 93 94 func g2b[P, Q any](x P, y Q) { 95 g2b(y, x) 96 } 97 98 // Here's an example of a recursive function call with variadic 99 // arguments and type inference inferring the type parameter of 100 // the caller (i.e., itself). 101 func max[T interface{ ~int }](x ...T) T { 102 var x0 T 103 if len(x) > 0 { 104 x0 = x[0] 105 } 106 if len(x) > 1 { 107 x1 := max(x[1:]...) 108 if x1 > x0 { 109 return x1 110 } 111 } 112 return x0 113 } 114 115 // When inferring channel types, the channel direction is ignored 116 // for the purpose of type inference. Once the type has been in- 117 // fered, the usual parameter passing rules are applied. 118 // Thus even if a type can be inferred successfully, the function 119 // call may not be valid. 120 121 func fboth[T any](chan T) {} 122 func frecv[T any](<-chan T) {} 123 func fsend[T any](chan<- T) {} 124 125 func _() { 126 var both chan int 127 var recv <-chan int 128 var send chan<-int 129 130 fboth(both) 131 fboth(recv /* ERROR "cannot use" */ ) 132 fboth(send /* ERROR "cannot use" */ ) 133 134 frecv(both) 135 frecv(recv) 136 frecv(send /* ERROR "cannot use" */ ) 137 138 fsend(both) 139 fsend(recv /* ERROR "cannot use" */) 140 fsend(send) 141 } 142 143 func ffboth[T any](func(chan T)) {} 144 func ffrecv[T any](func(<-chan T)) {} 145 func ffsend[T any](func(chan<- T)) {} 146 147 func _() { 148 var both func(chan int) 149 var recv func(<-chan int) 150 var send func(chan<- int) 151 152 ffboth(both) 153 ffboth(recv /* ERROR "does not match" */ ) 154 ffboth(send /* ERROR "does not match" */ ) 155 156 ffrecv(both /* ERROR "does not match" */ ) 157 ffrecv(recv) 158 ffrecv(send /* ERROR "does not match" */ ) 159 160 ffsend(both /* ERROR "does not match" */ ) 161 ffsend(recv /* ERROR "does not match" */ ) 162 ffsend(send) 163 } 164 165 // When inferring elements of unnamed composite parameter types, 166 // if the arguments are defined types, use their underlying types. 167 // Even though the matching types are not exactly structurally the 168 // same (one is a type literal, the other a named type), because 169 // assignment is permitted, parameter passing is permitted as well, 170 // so type inference should be able to handle these cases well. 171 172 func g1[T any]([]T) {} 173 func g2[T any]([]T, T) {} 174 func g3[T any](*T, ...T) {} 175 176 func _() { 177 type intSlice []int 178 g1([]int{}) 179 g1(intSlice{}) 180 g2(nil, 0) 181 182 type myString string 183 var s1 string 184 g3(nil, "1", myString("2"), "3") 185 g3(& /* ERROR "cannot use &s1 (value of type *string) as *myString value in argument to g3" */ s1, "1", myString("2"), "3") 186 _ = s1 187 188 type myStruct struct{x int} 189 var s2 myStruct 190 g3(nil, struct{x int}{}, myStruct{}) 191 g3(&s2, struct{x int}{}, myStruct{}) 192 g3(nil, myStruct{}, struct{x int}{}) 193 g3(&s2, myStruct{}, struct{x int}{}) 194 } 195 196 // Here's a realistic example. 197 198 func append[T any](s []T, t ...T) []T { panic(0) } 199 200 func _() { 201 var f func() 202 type Funcs []func() 203 var funcs Funcs 204 _ = append(funcs, f) 205 } 206 207 // Generic type declarations cannot have empty type parameter lists 208 // (that would indicate a slice type). Thus, generic functions cannot 209 // have empty type parameter lists, either. This is a syntax error. 210 211 func h[] /* ERROR "empty type parameter list" */ () {} 212 213 func _() { 214 h /* ERROR "cannot index" */ [] /* ERROR "operand" */ () 215 } 216 217 // Generic functions must have a function body. 218 219 func _ /* ERROR "generic function is missing function body" */ [P any]()