Finding the type of a variable through static analysis? [duplicate] - go

This question already has an answer here:
Golang static identifier resolution
(1 answer)
Closed 4 months ago.
How can I determine the type of a variable through static analysis?
Suppose I have the following code:
func doSomething(x interface{}) {}
func main() {
p := Person()
doSomething(p)
}
And I want to analyze doSomething(person), is it possible to get the type of Person through static analysis?
What if there were multiple levels of assignment?
p1 := Person()
p2 := p1
doSomething(p2)
or
parent := Parent()
p := Parent.Child() // type Person
doSomething(p)
The use case is that I have a generic function that is commonly used throughout the (very large) codebase, and would like to introduce a new type safe version of this function. To do this, I hope to automatically determine the "type" of the function and refactor it accordingly:
// old
DB.InsertRow(person)
// new
Person.InsertRow(person)

Finding the type of an expression through static analysis is non-trivial, and sometimes not possible, for details see Golang static identifier resolution.
The use case is that I have a generic function that is commonly used throughout the (very large) codebase, and would like to introduce a new type safe version of this function. To do this, I hope to automatically determine the "type" of the function and refactor it accordingly:
// old
DB.InsertRow(person)
// new
Person.InsertRow(person)
Just for refactoring purposes, I don't think it is worth the hassle to implement it.
What you may do is change the signature of DB.InsertRow() temporarily to accept only a specific type such as int or your custom type you're sure is not used anywhere (e.g. type tempFoo struct{}).
To what end? Doing so, the compiler will do the hard work for you. You will see error messages showing exactly the types your codebase is trying to pass to DB.InsertRow(), so I'd say mission accomplished.
For example this code compiles:
func doSomething(x interface{}) {}
func main() {
doSomething(image.Pt(1, 2))
doSomething("abc")
doSomething(image.Rect) // image.Rect is a function which we don't call,
// so we're passing a value of a function type here
}
If we change doSomething():
func doSomething(x int) {}
We get the types we're seeking for from the compiler:
./prog.go:10:14: cannot use image.Pt(1, 2) (value of type image.Point) as type int in argument to doSomething
./prog.go:11:14: cannot use "abc" (untyped string constant) as int value in argument to doSomething
./prog.go:12:14: cannot use image.Rect (value of type func(x0 int, y0 int, x1 int, y1 int) image.Rectangle) as type int in argument to doSomething

Using the advice from Golang static identifier resolution to use golang.org/x/tools/go/types, I found that this was pretty straight forward to do with the golang.org/x/tools/go/analysis package, which has the types info available alongside the parsed ast.
This was my solution:
package rewriter
import (
"go/ast"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
)
func run(pass *analysis.Pass) (interface{}, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.CallExpr)(nil),
}
inspect.Nodes(nodeFilter, func(node ast.Node, push bool) bool {
callExpr, ok := node.(*ast.CallExpr)
if !ok {
return true
}
funcExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
// check method name
if funcExpr.Sel.Name != "doSomething" {
return true
}
for _, arg := range callExpr.Args {
// lookup type of the arg
argType := pass.TypesInfo.Types[arg].Type
if argType.String() == "*rewriter.Person" {
// do whatever you want here
}
}
return false
})
return nil, nil
}
One can augment this to look at the receiver of the method and add refactoring logic as needed (using analysis.Diagnostic).

Related

How to declare and use a struct field which can store both string and int values?

I've the following struct:
type testCase struct {
input string
isValid bool
}
I want to use this struct in multiple tests and input could be either a string or an intetc.
I can convert the int input to string and convert it back to int while processing, or I can define two different structs e.g. testCaseInt and testCaseStruct which will solve my problem but how do I solve this by converting input to an interface?
I'm new to Go and tried Googling about this but couldn't find maybe because I don't know what to search for.
How to declare and use a variable which can store both string and int values in Go?
You cannot. Go's type system (as of Go 1.17) doesn't provide sum types.
You will have to wait for Go 1.18.
tl;dr the trade-off is between static typing and flexible containers.
Up to Go 1.17 you cannot have a struct field with different static types. The best you can have is interface{}, and then assert the dynamic type upon usage. This effectively allows you to have containers of testCases with either type at run time.
type testCase struct {
input interface{}
isValid bool
}
func main() {
// can initialize container with either type
cases := []testCase{{500, false}, {"foobar", true}}
// must type-assert when using
n := cases[0].(int)
s := cases[1].(string)
}
With Go 1.18, you can slightly improve on type safety, in exchange for less flexibility.
Parametrize the struct with a union. This statically restricts the allowed types, but the struct now must be instantiated explicitly, so you can't have containers with different instantiations. This may or may not be compatible with your goals.
type testCase[T int | string] struct {
input T
isValid bool
}
func main() {
// must instantiate with a concrete type
cases := []testCase[int]{
{500, false}, // ok, field takes int value
/*{"foobar", true}*/, // not ok, "foobar" not assignable to int
}
// cases is a slice of testCase with int fields
}
No, instantiating as testCase[any] is a red herring. First of all, any just doesn't satisfy the constraint int | string; even if you relax that, it's actually worse than the Go 1.17 solution, because now instead of using just testCase in function arguments, you must use exactly testCase[any].
Parametrize the struct with a union but still use interface{}/any as field type: (How) can I implement a generic `Either` type in go? . This also doesn't allow to have containers with both types.
In general, if your goal is to have flexible container types (slices, maps, chans) with either type, you have to keep the field as interface{}/any and assert on usage. If you just want to reuse code with static typing at compile-time and you are on Go 1.18, use the union constraint.
Method 1:
package main
import (
"fmt"
)
func main() {
var a interface{}
a = "hi"
if valString, ok := a.(string); ok {
fmt.Printf("String: %s", valString)
}
a = 1
if valInt, ok := a.(int); ok {
fmt.Printf("\nInteger: %d", valInt)
}
}
Method 2:
package main
import (
"fmt"
)
func main() {
print("hi")
print(1)
}
func print(a interface{}) {
switch t := a.(type) {
case int:
fmt.Printf("Integer: %v\n", t)
case string:
fmt.Printf("String: %v\n", t)
}
}
only you can do is this, change string with interface{}
check on play (it works fine)
https://go.dev/play/p/pwSZiZp5oVx
package main
import "fmt"
type testCase struct {
input interface{}
isValid bool
}
func main() {
test1 := testCase{}
test1.input = "STRING". // <-------------------STRING
fmt.Printf("input: %v \n", test1)
test2 := testCase{}
test2.input = 1 // <-------------------INT
fmt.Printf("input: %v \n", test2)
}

Passing a []fmt.Stringer parameter to a func [duplicate]

This question already has answers here:
Can I type assert a slice of interface values?
(2 answers)
Closed 3 years ago.
I have a type that implements the stringer interface
// RowID stores the ID of a single row in a table
type RowID []string
// String implements Stringer interface for RowID
func (r RowID) String() string {
return fmt.Sprintf("[%s]", strings.Join(r, ", "))
}
And I have a function that I want to pass a slice of this type (or any other type that implements the Stringer interface) to.
// PrintChanges ...
func PrintChanges(ids []fmt.Stringer) {
for _, id := range ids {
fmt.Println(id)
}
}
However, The go compiler gives me an error:
cannot use rowIDs (type []RowID) as type []fmt.Stringer in argument to PrintChanges
I can pass a RowID to a func that accepts a single fmt.Stringer
func PrintChange(id fmt.Stringer) {
fmt.Println(id)
}
...
PrintChange(RowID{"1", "24"})
But for some reason I am not able to pass a slice of RowID to a func that accepts a slice of fmt.Stringer. What am I missing?
Go Playground
Keep it simple
It is considered okay by professional Go programmers to repeat functions like this for every type, or to have a for loop over every slice you want to print. This is because Go aims to be as easy to read as possible, i.e. a person who reads a chunk of code for the first time should not be asking questions like "which function overload will this function call go to" (common pitfall in C++, Go does not have function overloads). So you can just write in main():
Playground: https://ideone.com/IL3rGR
for _, id := range rowIDs { fmt.Println(id) }
Simple and concise.
Note that fmt.Println(id) does not call your String() function
This is because the fmt library uses the reflect library and hardcodes behavior for the string type, which you are trying to replace. RowID instances are also string instances, the library always prefers string over its type aliases. I would say it is a bug in the library:
Library source: https://golang.org/src/fmt/print.go#L649
// Some types can be done without reflection.
switch f := arg.(type) {
...
case string:
p.fmtString(f, verb)
If you really want to
You can use a function that takes an interface{} and makes a runtime reflect type cast to a slice of Stringers. Note that this means you will not see type mismatches during compilation, only in runtime:
Playground: https://ideone.com/vlrBP9
func castToStringerSlice(iface interface{}) ([]fmt.Stringer, bool /* ok */) {
if reflect.TypeOf(iface).Kind() != reflect.Slice {
return nil, false
}
v := reflect.ValueOf(iface)
stringers := make([]fmt.Stringer, v.Len())
for i := 0; i < v.Len(); i++ {
stringers[i] = v.Index(i)
}
return stringers, true
}
func PrintChanges(iface_ids interface{}) {
ids, ok := castToStringerSlice(iface_ids)
if !ok {
log.Fatal(errors.New("the argument to PrintChanges must be a slice of Stringers"))
}
for _, id := range ids {
fmt.Println(id)
}
}
Resources:
Go documentation: Why does Go not support overloading of methods and operators?
Go documentation: Why does Go not have generic types?
Stack Overflow: Express function that takes any slice
Stack Overflow: Range over interface{} which stores a slice
Go documentation: Package reflect

Cannot Range Over List Type Interface {} In Function Using Go

Cannot Range Over List Type Interface {} In Function Using Go.
for me is important then i execute for in a function.
How can fix?
package main
import (
"fmt"
)
type MyBoxItem struct {
Name string
}
type MyBox struct {
Items []MyBoxItem
}
func (box *MyBox) AddItem(item MyBoxItem) []MyBoxItem {
box.Items = append(box.Items, item)
return box.Items
}
func PrintCustomArray(list interface{}) interface{} {
//items := reflect.ValueOf(list)
for _, v := range list {
fmt.Println(v.Key,v.Value)
}
return 0
}
func main() {
items := []MyBoxItem{}
item := MyBoxItem{Name: "Test Item 1"}
box := MyBox{items}
box.AddItem(item)
fmt.Println((box.Items))
PrintCustomArray(box.Items)
}
https://play.golang.org/p/ZcIBLMliq3
Error : cannot range over list (type interface {})
How can fix?
Note
The answer below describes, in broad strokes, 2 possible approaches: using interfaces, and using specific types. The approach focusing on interfaces is mentioned for completeness sake. IMHO, the case you've presented is not a viable use-case for interfaces.
Below, you'll find a link to a playground example that uses both techniques. It should be apparent to anyone that the interface approach is too cumbersome if for this specific case.
Quite apart from the fact that you don't really seem to be too familiar with how loops work in go (v.Key and v.Value are non-existent fields for example), I'll attempt to answer your question.
You are passing a list to your function, sure enough, but it's being handled as an interface{} type. That means your function accepts, essentially, any value as an argument. You can't simply iterate over them.
What you can do is use type assertions to convert the argument to a slice, then another assertion to use it as another, specific interface:
type Item interface{
key() string
val() string
}
func (i MyBoxItem) key() string {
return i.Key
}
func (i MyBoxItem) val() string {
return i.Value
}
func PrintCustomArray(list interface{}) error {
listSlice, ok := list.([]interface{})
if !ok {
return fmt.Errorf("Argument is not a slice")
}
for _, v := range listSlice {
item, ok := v.(Item)
if !ok {
return fmt.Errorf("element in slice does not implement the Item interface")
}
fmt.Println(item.key(), item.val())
}
return nil
}
But let's be honest, a function like this only works if a slice is passed as an argument. So having that first type assertion in there makes no sense whatsoever. At the very least, changing the function to something like this makes a lot more sense:
func PrintCustomArray(list []interface{})
Then, because we're not expecting an array as such, but rather a slice, the name should be changed to PrintCustomSlice.
Lastly, because we're using the same type assertion for every value in the slice, we might as well change the function even more:
// at this point, we'll always return 0, which is pointless
// just don't return anything
func PrintCustomSlice(list []Item) {
for _, v := range list {
fmt.Println(v.key(), v.val())
}
}
The advantages of a function like this is that it can still handle multiple types (all you have to do is implement the interface). You don't need any kind of expensive operations (like reflection), or type assertions.
Type assertions are very useful, but in a case like this, they merely serve to hide problems that would otherwise have resulted in a compile-time error. Go's interface{} type is a very useful thing, but you seem to be using it to get around the type system. If that's what you want to achieve, why use a typed language in the first place?
Some closing thoughts/remarks: If your function is only going to be used to iterate over specific "thing", you don't need the interfaces at all, simply specify the type you're expecting to be passed to the function in the first place. In this case that would be:
func PrintCustomSlice(list []MyBoxItem) {
for _, v := range list {
fmt.Println(v.Key, v.Value)
}
}
Another thing that I've noticed is that you seem to be exporting everything (all functions, types, and fields start with a capital letter). This, in go, is considered bad form. Only export what needs to be public. In the main package, that usually means you're hardly export anything.
Lastly, as I mentioned at the start: you don't seem to have a firm grasp on the basics just yet. I'd strongly recommend you go through the interactive tour. It covers the basics nicely, but shows you the features of the language at a decent pace. It doesn't take long, and is well worth taking a couple of hours to complete
Playground demo
It's possible to implement PrintCustomArray using the reflect package, but most experienced Go programmers will write a simple for loop:
for _, i := range box.Items {
fmt.Println("Name:", i.Name)
}
https://play.golang.org/p/RhubiCpry0
You can also encapsulate it in a function:
func PrintCustomArray(items []MyBoxItem) {
for _, i := range items {
fmt.Println("Name:", i.Name)
}
}
https://play.golang.org/p/c4EPQIx1AH
Here since you are returning box.Items from AddItem(), Items is of the type []MyBoxItem , so list should be of type []MyBoxItem .Moreover you are returning 0 in PrintCustomArray and the return type you have set is {}interface.
func PrintCustomArray(list []MyBoxItem) {
//items := reflect.ValueOf(list)
for i, v := range list {
fmt.Println(i, v)
}
//return 0
}
Again, MyBoxItem struct has only one variable named Name so v.key v.value won't make any sense.
This is what the proper code should look like https://play.golang.org/p/ILoUwEWv6Y .
You need to clear your understanding about interfaces in go. This might help https://golang.org/doc/effective_go.html#interfaces_and_types .

How to resolve whether pass objects via interface{} have not initializated fields

I have problem with resolve whether object which was pass as interface to function hasn't initializated fields, like object which was defined as just someObject{} is a empty, because all fields, has value 0, or nil
Problem becomes more complicated if I pass diffrent objects, because each object have diffrent type field value so on this moment I don't find universal way to this.
Example
func main(){
oo := objectOne{}
ot := objectTwo{}
oth := objectThree{"blah" , "balbal" , "blaal"}
resolveIsNotIntialized(oo)
resolveIsNotIntialized(ot)
resolveIsNotIntialized(oth)
}
func resolveIsNotIntialized(v interface{}) bool{
// and below, how resolve that oo and ot is empty
if (v.SomeMethodWhichCanResolveThatAllFiledIsNotIntialized){
return true
}
return false
}
I want to avoid usage switch statement like below, and additional function for each object, ofcorse if is possible.
func unsmartMethod(v interface{}) bool{
switch v.(type){
case objectOne:
if v == (objectOne{}) {
return true
}
// and next object, and next....
}
return false
}
As Franck notes, this is likely a bad idea. Every value is always initialized in Go. Your actual question is whether the type equals its Zero value. Generally the Zero value should be designed such that it is valid. The better approach would generally be to create an interface along the lines of:
type ZeroChecker interface {
IsZero() bool
}
And then attach that to whatever types you want to check. (Or possibly better: create an IsValid() test instead rather than doing your logic backwards.)
That said, it is possible to check this with reflection, by comparing it to its Zero.
func resolveIsNotIntialized(v interface{}) bool {
t := reflect.TypeOf(v)
z := reflect.Zero(t).Interface()
return reflect.DeepEqual(v, z)
}
(You might be able to get away with return v == z here; I haven't thought through all the possible cases.)
I don’t think there is a good reason (in idiomatic Go) to do what you are trying to do. You need to design your structs so that default values (nil, empty string, 0, false, etc.) are valid and represent the initial state of your object. Look at the source of the standard library, there are lots of examples of that.
What you are suggesting is easily doable via Reflection but it will be slow and clunky.
You could narrow the type which your function takes as an argement a little, not take an interface{} but accept one that allows you to check for non-zero values, say type intercae{nonZero() bool} as in the example code below. This will not tell you explicitly that it hasn't been set to the zero value, but that it is not zero.
type nonZeroed interface {
nonZero() bool
}
type zero struct {
hasVals bool
}
func (z zero) nonZero() bool {
return z.hasVals
}
type nonZero struct {
val int
}
func (nz nonZero) nonZero() bool {
return nz.val != 0
}
type alsoZero float64
func (az alsoZero) nonZero() bool {
return az != 0.0
}
func main() {
z := zero{}
nz := nonZero{
val: 1,
}
var az alsoZero
fmt.Println("z has values:", initialized(z))
fmt.Println("nz has values:", initialized(nz))
fmt.Println("az has values:", initialized(az))
}
func initialized(a nonZeroed) bool {
return a.nonZero()
}
Obviously as the type get more complex additional verification would need to be made that it was "nonZero". This type of pattern could be used to check any sort condition.

Optional Parameters in Go?

Can Go have optional parameters? Or can I just define two different functions with the same name and a different number of arguments?
Go does not have optional parameters nor does it support method overloading:
Method dispatch is simplified if it
doesn't need to do type matching as
well. Experience with other languages
told us that having a variety of
methods with the same name but
different signatures was occasionally
useful but that it could also be
confusing and fragile in practice.
Matching only by name and requiring
consistency in the types was a major
simplifying decision in Go's type
system.
A nice way to achieve something like optional parameters is to use variadic args. The function actually receives a slice of whatever type you specify.
func foo(params ...int) {
fmt.Println(len(params))
}
func main() {
foo()
foo(1)
foo(1,2,3)
}
You can use a struct which includes the parameters:
type Params struct {
a, b, c int
}
func doIt(p Params) int {
return p.a + p.b + p.c
}
// you can call it without specifying all parameters
doIt(Params{a: 1, c: 9})
The main advantage over an ellipsis (params ...SomeType) is that you can use the param struct with different parameter types.
For arbitrary, potentially large number of optional parameters, a nice idiom is to use Functional options.
For your type Foobar, first write only one constructor:
func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){
fb := &Foobar{}
// ... (write initializations with default values)...
for _, op := range options{
err := op(fb)
if err != nil {
return nil, err
}
}
return fb, nil
}
where each option is a function which mutates the Foobar. Then provide convenient ways for your user to use or create standard options, for example :
func OptionReadonlyFlag(fb *Foobar) error {
fb.mutable = false
return nil
}
func OptionTemperature(t Celsius) func(*Foobar) error {
return func(fb *Foobar) error {
fb.temperature = t
return nil
}
}
Playground
For conciseness, you may give a name to the type of the options (Playground) :
type OptionFoobar func(*Foobar) error
If you need mandatory parameters, add them as first arguments of the constructor before the variadic options.
The main benefits of the Functional options idiom are :
your API can grow over time without breaking existing code, because the constuctor signature stays the same when new options are needed.
it enables the default use case to be its simplest: no arguments at all!
it provides fine control over the initialization of complex values.
This technique was coined by Rob Pike and also demonstrated by Dave Cheney.
Neither optional parameters nor function overloading are supported in Go. Go does support a variable number of parameters: Passing arguments to ... parameters
No -- neither. Per the Go for C++ programmers docs,
Go does not support function
overloading and does not support user
defined operators.
I can't find an equally clear statement that optional parameters are unsupported, but they are not supported either.
You can pass arbitrary named parameters with a map. You will have to assert types with "aType = map[key].(*foo.type)" if the parameters have non-uniform types.
type varArgs map[string]interface{}
func myFunc(args varArgs) {
arg1 := "default"
if val, ok := args["arg1"]; ok {
arg1 = val.(string)
}
arg2 := 123
if val, ok := args["arg2"]; ok {
arg2 = val.(int)
}
fmt.Println(arg1, arg2)
}
func Test_test() {
myFunc(varArgs{"arg1": "value", "arg2": 1234})
}
Go doesn’t support optional parameters , default values and function overloading but you can use some tricks to implement the same.
Sharing one example where you can have different number and type of arguments in one function. It’s a plain code for easy understanding you need to add error handling and some logic.
func student(StudentDetails ...interface{}) (name string, age int, area string) {
age = 10 //Here Age and area are optional params set to default values
area = "HillView Singapore"
for index, val := range StudentDetails {
switch index {
case 0: //the first mandatory param
name, _ = val.(string)
case 1: // age is optional param
age, _ = val.(int)
case 2: //area is optional param
area, _ = val.(string)
}
}
return
}
func main() {
fmt.Println(student("Aayansh"))
fmt.Println(student("Aayansh", 11))
fmt.Println(student("Aayansh", 15, "Bukit Gombak, Singapore"))
}
So I feel like I'm way late to this party but I was searching to see if there was a better way to do this than what I already do. This kinda solves what you were trying to do while also giving the concept of an optional argument.
package main
import "fmt"
type FooOpts struct {
// optional arguments
Value string
}
func NewFoo(mandatory string) {
NewFooWithOpts(mandatory, &FooOpts{})
}
func NewFooWithOpts(mandatory string, opts *FooOpts) {
if (&opts) != nil {
fmt.Println("Hello " + opts.Value)
} else {
fmt.Println("Hello")
}
}
func main() {
NewFoo("make it work please")
NewFooWithOpts("Make it work please", &FooOpts{Value: " World"})
}
Update 1:
Added a functional example to show functionality versus the sample
You can encapsulate this quite nicely in a func similar to what is below.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
fmt.Println(prompt())
}
func prompt(params ...string) string {
prompt := ": "
if len(params) > 0 {
prompt = params[0]
}
reader := bufio.NewReader(os.Stdin)
fmt.Print(prompt)
text, _ := reader.ReadString('\n')
return text
}
In this example, the prompt by default has a colon and a space in front of it . . .
:
. . . however you can override that by supplying a parameter to the prompt function.
prompt("Input here -> ")
This will result in a prompt like below.
Input here ->
You could use pointers and leave them nil if you don't want to use them:
func getPosts(limit *int) {
if optParam != nil {
// fetch posts with limit
} else {
// fetch all posts
}
}
func main() {
// get Posts, limit by 2
limit := 2
getPosts(&limit)
// get all posts
getPosts(nil)
}
Go language does not support method overloading, but you can use variadic args just like optional parameters, also you can use interface{} as parameter but it is not a good choice.
I ended up using a combination of a structure of params and variadic args. This way, I didn't have to change the existing interface which was consumed by several services and my service was able to pass additional params as needed. Sample code in golang playground: https://play.golang.org/p/G668FA97Nu
I am a little late, but if you like fluent interface you might design your setters for chained calls like this:
type myType struct {
s string
a, b int
}
func New(s string, err *error) *myType {
if s == "" {
*err = errors.New(
"Mandatory argument `s` must not be empty!")
}
return &myType{s: s}
}
func (this *myType) setA (a int, err *error) *myType {
if *err == nil {
if a == 42 {
*err = errors.New("42 is not the answer!")
} else {
this.a = a
}
}
return this
}
func (this *myType) setB (b int, _ *error) *myType {
this.b = b
return this
}
And then call it like this:
func main() {
var err error = nil
instance :=
New("hello", &err).
setA(1, &err).
setB(2, &err)
if err != nil {
fmt.Println("Failed: ", err)
} else {
fmt.Println(instance)
}
}
This is similar to the Functional options idiom presented on #Ripounet answer and enjoys the same benefits but has some drawbacks:
If an error occurs it will not abort immediately, thus, it would be slightly less efficient if you expect your constructor to report errors often.
You'll have to spend a line declaring an err variable and zeroing it.
There is, however, a possible small advantage, this type of function calls should be easier for the compiler to inline but I am really not a specialist.
Another possibility would be to use a struct which with a field to indicate whether its valid. The null types from sql such as NullString are convenient. Its nice to not have to define your own type, but in case you need a custom data type you can always follow the same pattern. I think the optional-ness is clear from the function definition and there is minimal extra code or effort.
As an example:
func Foo(bar string, baz sql.NullString){
if !baz.Valid {
baz.String = "defaultValue"
}
// the rest of the implementation
}

Resources