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 7package p 8 9// Reverse is a generic function that takes a []T argument and 10// reverses that slice in place. 11func 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 21func _() { 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. 42func 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. 52var _ = new[int]() 53var _ *float64 = new[float64]() // the result type is indeed *float64 54 55// A function may have multiple type parameters, of course. 56func 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. 62var s = foo[int, string, float64](1, []string{"first"}, new[float64]()) 63 64// Or we can use type inference. 65var _ float64 = foo(42, []float64{1.0}, &s) 66 67// Type inference works in a straight-forward manner even 68// for variadic functions. 69func variadic[A, B any](A, B, ...B) int { panic(0) } 70 71// var _ = variadic(1) // ERROR "not enough arguments" 72var _ = variadic(1, 2.3) 73var _ = variadic(1, 2.3, 3.4, 4.5) 74var _ = 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. 78func f1[T any](x T) { 79 f1(x) 80} 81 82func f2a[T any](x, y T) { 83 f2a(x, y) 84} 85 86func f2b[T any](x, y T) { 87 f2b(y, x) 88} 89 90func g2a[P, Q any](x P, y Q) { 91 g2a(x, y) 92} 93 94func 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). 101func 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 121func fboth[T any](chan T) {} 122func frecv[T any](<-chan T) {} 123func fsend[T any](chan<- T) {} 124 125func _() { 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 143func ffboth[T any](func(chan T)) {} 144func ffrecv[T any](func(<-chan T)) {} 145func ffsend[T any](func(chan<- T)) {} 146 147func _() { 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 172func g1[T any]([]T) {} 173func g2[T any]([]T, T) {} 174func g3[T any](*T, ...T) {} 175 176func _() { 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 198func append[T any](s []T, t ...T) []T { panic(0) } 199 200func _() { 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 211func h[] /* ERROR "empty type parameter list" */ () {} 212 213func _() { 214 h /* ERROR "cannot index" */ [] /* ERROR "operand" */ () 215} 216 217// Generic functions must have a function body. 218 219func _ /* ERROR "generic function is missing function body" */ [P any]() 220