I am very new to Go, so I am sorry for that noob question.
In JavaScript console.log(window) returns all objects inside of window. In PHP var_dump(new DateTime()) returns all objects inside of DateTime().
Is there a function in Go that will return all objects from a given object? For example Println should be returned if fmt is given.
Try executing go doc fmt in a terminal to produce a description of the "fmt" package and a listing of the functions it exports, or referring to the fmt package documentation at https://golang.org. In go, as in most other static/compiled languages, users are expected to refer to documentation (or docs) which describe the programming language and its libraries. Contrast this to some dynamic/scripting languages, which often make it easy to query any object to discover its usable properties.
At runtime, you can get a helpful printout of any arbitrary value by using the %#v formatting verb to produce a go syntax representation of the value, e.g.
xs := []int{1, 2, 3}
fmt.Printf("OK: xs=%#v\n", xs)
// OK: xs=[]int{1, 2, 3}
Note that the package "fmt" is not a value in the go language so it cannot be printed at runtime as such.
In Go is possible does something similar, but don't work for all.
func main() {
//arrays
a := []int{1,2,3,4}
fmt.Printf("%v\r\n", a) //print [1 2 3 4]
//maps
b := map[string]int{
"a":1,
"b":2,
}
fmt.Printf("%v\r\n", b) //print map[a:1 b:2]
//structs
c := struct{
A int
B int
}{1,2}
d := struct{
C struct{
A int
B int
}
D int
}{c,2}
fmt.Printf("%v\r\n", d) //print {{1 2} 2}
}
See in: https://play.golang.org/p/vzlCsOG497h
If you pass fmt occurs error because it is a package. The error is:
Error: use of package fmt without selector
I hope this helps (too)!
GO OOP, & inheritance
Go does not have objects, but we do have custom types and interfaces that we can attach attributes, functions and other types to.
What specifically are you trying to do? If you're looking for a var_dump:
USING fmt.Println
someErr := fmt.Errorf("custom type error")
fmt.Println(someErr)
Println formats using the default formats for its operands and writes to standard output.
USING fmt.Printf
someErr := fmt.Errorf("custom type error")
fmt.Printf("This is an error:%v A num: %v A str", someErr, 19, "Stackoverflow")
Printf formats according to a format specifier and writes to standard output.
USING fmt.Sprintf
someErr := fmt.Errorf("custom type error")
// someStr now contains the string formatted as shown below
someStr := fmt.Sprintf("This is an error:%v A num: %v A str", someErr, 19, "Stackoverflow")
Sprintf formats according to a format specifier and returns the resulting string.
Here is an example of my personal preference when outputting var data:
https://play.golang.org/p/8dpeE-fray_J
I hope this helps!
Related
This question already has answers here:
Go Generics - Unions
(2 answers)
Closed 11 months ago.
Can you write a function in Go whose parameter can be two different types? For example, if I write a simple function that takes in an array/slice of int and simply returns the first value:
func First(array []int) int {
return array[0]
}
Is there a way to type this such that we can also pass in a []string, etc.? In TypeScript for example, we can do it like such without having to type the array as any:
const first = (array: (number | string)[]): number | string => {
return array[0];
};
I've seen answers explaining the use of interface{} for situations like this... and maybe that's the only way, but it seems to close to any in TS and it feels like there might be a better way of doing this.
(I haven't used Go for a few years, long before they introduced generics - so I'm basing my answer off their documentation for generics)
TypeScript's "generics" (in quotes) aren't really comparable to Go's generics. TypeScript is all about being able to describe an interface (in an abstract sense) for a runtime system built around type-erasure (i.e. JavaScript), while Go's is... honestly, I have no idea. I just don't know how Go's generics are implemented nor their runtime characteristics: Articles on Go's generics, even from the language authors blog or their own documentation site fail to mention key-terms like type erasure, reified generics, (template) instantiation or monomorph, so if anyone has a better understanding please edit this post, or let me know in a comment!
Anyway, the good news is that as-of the Go 1.18 Beta, its support for generics includes support for generic constraints, but also support for union types as a constraint for generic type parameters (though I haven't yet found any information regarding support for other ADTs like product types and intersection types).
(Note that, at least for now, Go won't support union types as concrete types, but in practice that shouldn't be an issue)
In your case, if you want a function that returns the first element of a slice that could be either []int or []string (or returns some default-value if the slice is empty), then you can do this:
func First[T int | string](arr []T, ifEmpty T) T {
for _, v := range arr {
return v
}
return ifEmpty
}
While at first-glance you might think that this would allow for the arr slice to simultaneously contain both int and string values, this is not allowed (see below). Remember that generic parameters arguments are supplied by the caller and have to be valid concrete types, so First can only be instantiated as either First[int] or First[string], which in-turn implies that arr can be either []int or []string.
Anyway, the full example below compiles and runs in the Go dev branch on the Go playground:
package main
import "fmt"
func First[T int | string](arr []T, ifEmpty T) T {
for _, v := range arr {
return v
}
return ifEmpty
}
func main() {
// First[int]:
arrayOfInts := []int{2, 3, 5, 7, 11, 13}
firstInt := First(arrayOfInts, -1)
fmt.Println(firstInt) // 2
// First[string]:
arrayOfStrings := []string{"life", "is short", "and love is always over", "in the morning"}
firstString := First(arrayOfStrings, "empty")
fmt.Println(firstString) // "life"
}
You can also extract the constraint T int | string and move it to an interface, and then use that as the constraint, which I personally think is easier to read, especially when you might need to repeat the same constraint in multiple places:
type IntOrString interface {
int | string
}
func First[T IntOrString](arr []T, ifEmpty T) T {
for _, v := range arr {
return v
}
return ifEmpty
}
Things you can't do...
Note that Go does not (currently, at least) allow using a type that describes a union as a variable's type by itself (nor can you use as a slice's element type either); you can only use a union as a constraint, otherwise you'll get the "interface contains type constraints" error. Which means you can't describe an array that can contain both int and string values and then use that interface for a concrete array type:
package main
import "fmt"
type IntOrString interface {
int | string
}
func First[T IntOrString](arr []T, ifEmpty T) T {
for _, v := range arr {
return v
}
return ifEmpty
}
func main() {
arrayOfIntsOrStrings := []IntOrString{2, "foo", 3, "bar", 5, "baz", 7, 11, 13} // ERROR: interface contains type constraints
firstValue := First(arrayOfIntsOrStrings, -1)
fmt.Println(firstValue)
}
./prog.go:19:28: interface contains type constraints
Go build failed.
I was reading the source code of the Middleware's chaining software Alice and found the expression:
func New(constructors ...Constructor) Chain {
return Chain{append(([]Constructor)(nil), constructors...)}
}
I have no problem with the code at all, except that i have never seen the expression ([]Slice)(nil) before. Does anybody have any information about this sort of expression?
It copies the constructors argument into a new slice, assigned it to a field in the Chain literal, and returns the new struct.
It is equivalent to
func New(constructors ...Constructor) Chain {
var tmp []Constructor
tmp = append(tmp, constructors...)
return Chain{tmp}
}
The author of alice here, just randomly clicked on this question. :)
The other answers explain what the append(nil, ...) does - I use it throughout the library to copy the slices that the user passes in.
Now, Go does not allow to simply use append(nil, someElement) because the type of nil is unknown. ([]Constructor)(nil) is casting nil to the type []Constructor in order to avoid this. This is a type conversion, same as, say, int64(123) or (*int)(nil).
This is a minimal example where the compiler errors out because of an untyped nil:
a := ([]int)(nil)
a = append(a, 1, 2, 3) // works fine, a is of type []int
var b []int
b = append(b, 1, 2, 3) // works fine, b is of type []int
c := nil
c = append(c, 1, 2, 3) // compiler error: the type of c is unknown
The section of appending to slices on the specification, mentions the following example:
var t []interface{}
t = append(t, 42, 3.1415, "foo") // t == []interface{}{42, 3.1415, "foo"}
I'm confused here, why can we append values of int, float and string to a slice whose elements are of interface type? And why is the result of the append like that? I tried hard/long, but I don't get it.
Because:
all types implement the empty interface
For details read over the ref spec for interfaces.
interface is similar to Object in java where all types/classes/etc are also an Object.
You can see this effect by using reflect:
package main
import (
"fmt"
"reflect"
)
func main() {
var t []interface{}
z := append(t, "asdf", 1, 2.0)
fmt.Println(z)
for i := range z {
fmt.Println(reflect.TypeOf(z[i]))
}
}
Output:
[asdf 1 2]
string
int
float64
Why is it like this? Well, think about serialization especially of JSON objects; the types can be string, int, object, etc. This allows for deserialization without specifying a fully mapped struct (maybe you don't care and want only some of the data, etc). Basically, it allows you to have a form of "weak typing" in Go; while still being able to have strong typing.
As mentioned below, reflect identifies the type for you. When programming though, you may have to do it manually.
I want to swap two numbers using interface but the interface concept is so confusing to me.
http://play.golang.org/p/qhwyxMRj-c
This is the code and playground. How do I use interface and swap two input numbers? Do I need to define two structures?
type num struct {
value interface{}
}
type numbers struct {
b *num
c *num
}
func (a *num) SwapNum(var1, var2 interface{}) {
var a num
temp := var1
var1 = var2
var2 = temp
}
func main() {
a := 1
b := 2
c := 3.5
d := 5.5
SwapNum(a, b)
fmt.Println(a, b) // 2 1
SwapNum(c, d)
fmt.Println(c, d) // 5.5 3.5
}
First of all, the interface{} type is simply a type which accepts all values as it is an interface with an empty method set and every type can satisfy that. int for example does not have any methods, neither does interface{}.
For a method which swaps the values of two variables you first need to make sure these variables are actually modifiable. Values passed to a function are always copied (except reference types like slices and maps but that is not our concern at the moment). You can achieve modifiable parameter by using a pointer to the variable.
So with that knowledge you can go on and define SwapNum like this:
func SwapNum(a interface{}, b interface{})
Now SwapNum is a function that accepts two parameters of any type.
You can't write
func SwapNum(a *interface{}, b *interface{})
as this would only accept parameters of type *interface{} and not just any type.
(Try it for yourself here).
So we have a signature, the only thing left is swapping the values.
func SwapNum(a interface{}, b interface{}) {
*a, *b = *b, *a
}
No, this will not work that way. By using interface{} we must do runtime type assertions to check whether we're doing the right thing or not. So the code must be expanded using the reflect package. This article might get you started if you don't know about reflection.
Basically we will need this function:
func SwapNum(a interface{}, b interface{}) {
ra := reflect.ValueOf(a).Elem()
rb := reflect.ValueOf(b).Elem()
tmp := ra.Interface()
ra.Set(rb)
rb.Set(reflect.ValueOf(tmp))
}
This code makes a reflection of a and b using reflect.ValueOf() so that we can
inspect it. In the same line we're assuming that we've got pointer values and dereference
them by calling .Elem() on them.
This basically translates to ra := *a and rb := *b.
After that, we're making a copy of *a by requesting the value using .Interface()
and assigning it (effectively making a copy).
Finally, we set the value of a to b with [ra.Set(rb)]5, which translates to *a = *b
and then assigning b to a, which we stored in the temp. variable before. For this,
we need to convert tmp back to a reflection of itself so that rb.Set() can be used
(it takes a reflect.Value as parameter).
Can we do better?
Yes! We can make the code more type safe, or better, make the definition of Swap type safe
by using reflect.MakeFunc. In the doc (follow the link) is an example which is very
like what you're trying. Essentially you can fill a function prototype with content
by using reflection. As you supplied the prototype (the signature) of the function the
compiler can check the types, which it can't when the value is reduced to interface{}.
Example usage:
var intSwap func(*int, *int)
a,b := 1, 0
makeSwap(&intSwap)
intSwap(&a, &b)
// a is now 0, b is now 1
The code behind this:
swap := func(in []reflect.Value) []reflect.Value {
ra := in[0].Elem()
rb := in[1].Elem()
tmp := ra.Interface()
ra.Set(rb)
rb.Set(reflect.ValueOf(tmp))
return nil
}
makeSwap := func(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
v := reflect.MakeFunc(fn.Type(), swap)
fn.Set(v)
}
The code of swap is basically the same as that of SwapNum. makeSwap is the same
as the one used in the docs where it is explained pretty well.
Disclaimer: The code above makes a lot of assumptions about what is given and
what the values look like. Normally you need to check, for example, that the given
values to SwapNum actually are pointer values and so forth. I left that out for
reasons of clarity.
In Go, in order to iterate over an array/slice, you would write something like this:
for _, v := range arr {
fmt.Println(v)
}
However, I want to iterate over array/slice which includes different types (int, float64, string, etc...). In Python, I can write it out as follows:
a, b, c = 1, "str", 3.14
for i in [a, b, c]:
print(i)
How can I do such a work in Go? As far as I know, both array and slice are supposed to allow only same-type object, right? (say, []int allows only int type object.)
Thanks.
As Go is a statically typed language, that won't be as easy as in Python. You will have to resort to type assertions, reflection or similar means.
Take a look at this example:
package main
import (
"fmt"
)
func main() {
slice := make([]interface{}, 3)
slice[0] = 1
slice[1] = "hello"
slice[2] = true
for _, v := range slice {
switch v.(type) {
case string:
fmt.Println("We have a string")
case int:
fmt.Println("That's an integer!")
// You still need a type assertion, as v is of type interface{}
fmt.Printf("Its value is actually %d\n", v.(int))
default:
fmt.Println("It's some other type")
}
}
}
Here we construct a slice with the type of an empty interface (any type implements it), do a type switch and handle the value based on the result of that.
Unfortunately, you'll need this (or a similar method) anywhere where you'll be dealing with arrays of unspecified type (empty interface). Moreover, you'll probably need a case for every possible type, unless you have a way to deal with any object you could get.
One way would be to make all of the types you want to store implement some interface of yours and then only use those objects through that interface. That's kind of how fmt handles generic arguments – it simply calls String() on any object to get its string representation.