I have an interface in go
which wants to support saving and loading results in different databases and I want to support different types.
package cfgStorage
type WritableType interface {
~int | ~string | ~float64
}
type ConfigStorage[K, V WritableType] interface {
get(key K) (V, error)
set(key K, value V) (bool, error)
}
func GetValue[K, V WritableType, C ConfigStorage[K, V]](storage C, key K) (V, error) {
res, err := storage.get(key)
return res, err
}
func SetValue[K, V WritableType, C ConfigStorage[K, V]](storage C, key K, value V) (bool, error) {
res, err := storage.set(key, value)
return res, err
}
I implemented fileSystem storage for this interface as below:
type FileSystemStorage[K, V WritableType] struct {
}
func (f FileSystemStorage[K, V]) get(key K) (V, error) {
/// my code to load data from json file
}
func (f FileSystemStorage[K, V]) set(key K, value V) (bool, error) {
/// my code to save data as json file
}
BTW when I try to get an instance from fileSystem
and SetValue
it works, but for GetValue
I faced a compiler error, my test code is as following:
var fileStorage cfgStorage.FileSystemStorage[string, string]
setResult, _ := cfgStorage.SetValue(fileStorage, "key", "value")
if setResult == false {
t.Error()
}
var result string
result, _ = cfgStorage.GetValue(fileStorage, "key")
The compile error is in the line where I called GetValue
:
cannot infer V
If you have any idea how to solve this issue please let me know!
This program now works without specifying the type constraints, because type inference now considers the types used in interface methods. From the release notes:
Type inference now also considers methods when a value is assigned to an interface: type arguments for type parameters used in method signatures may be inferred from the corresponding parameter types of matching methods.
Therefore you can simply call:
result, _ = GetValue(fileStorage, "key")
Playground: https://go.dev/play/p/XBuOTREHd5Y
In the function GetValue
, it's not possible to infer the type of V
with only the provided arguments storage C
and key K
.
You are asking to infer V
from the concrete type that implements the generic constraint ConfigStorage[K, V]
. The current type inference algorithm doesn't support this. Related issues in the Go github repository are 41176: cannot infer generic interface types , as well as 50484 and 40018.
Also relevant proposal section about type inference:
We can use function argument type inference for a function call to deduce type arguments from the types of the non-type arguments. We can use constraint type inference to deduce unknown type arguments from known type arguments.
So you could argue that C
is not actually known, you only know that it implements the constraint ConfigStorage[K, V]
.
You must call GetValue
with explicit type parameters:
// first string for K, second string for V
GetValue[string, string](fileStorage, "key")
Fixed playground: https://gotipplay.golang.org/p/KoYZ3JMEz2N