github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/const/const_race.go (about) 1 //go:build race 2 3 package main 4 5 import ( 6 "reflect" 7 "runtime" 8 ) 9 10 func Const[T any](v *T) struct{} { 11 go deepRaceRead(reflect.ValueOf(v)) 12 return struct{}{} 13 } 14 15 func deepRaceRead(v reflect.Value) { 16 _ = runtime.KeepAlive 17 switch v.Type().Kind() { 18 default: 19 panic("unhandled type") 20 case reflect.Bool, 21 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 22 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 23 reflect.Uintptr, 24 reflect.Float32, reflect.Float64, 25 reflect.Complex64, reflect.Complex128: 26 runtime.RaceRead(v.Addr().UnsafePointer()) 27 case reflect.Ptr: 28 if v.IsNil() { 29 return 30 } 31 deepRaceRead(v.Elem()) 32 case reflect.String: 33 runtime.RaceRead(v.UnsafePointer()) 34 case reflect.Array, reflect.Slice: 35 // TODO: use runtime.RaceReadRange 36 for i := 0; i < v.Len(); i++ { 37 deepRaceRead(v.Index(i)) 38 } 39 case reflect.Map: 40 if v.IsNil() { 41 return 42 } 43 iter := v.MapRange() 44 for iter.Next() { 45 deepRaceRead(iter.Value()) 46 } 47 case reflect.Struct: 48 for i := 0; i < v.NumField(); i++ { 49 deepRaceRead(v.Field(i)) 50 } 51 } 52 }