func main() {
fmt.Println(reflect.TypeOf(1)) //int
fmt.Println(reflect.TypeOf(0.1)) //float64
fmt.Println(reflect.TypeOf("hi")) //string
fmt.Println(reflect.TypeOf('c')) //int32
fmt.Println(reflect.TypeOf(1234567890)) //int
fmt.Println()
i := 1
j := int16(i)
k := int32(i)
fmt.Println(reflect.TypeOf(i)) //int (uint)
fmt.Println(reflect.TypeOf(j)) //int16
fmt.Println(reflect.TypeOf(k)) //int32
}
func main() {
var one int = 1
var two = 2
three := 3
var four, five int = 4, 5
fmt.Println(one, two, three, four, five)
}
type Status int
const (
Processing Status = iota
Printed
Shipped
Delivered
Canceled
)
func main() {
s1 := Printed
switch s1 {
case Processing:
fmt.Println("still being processed")
case Printed:
fmt.Println("pritned")
default:
fmt.Println("unknown status")
}
}
func check(e error) {
if e != nil {
panic(e)
}
}
data, err := Foo(1)
check(err)
data, err := Foo2()
check(err)
...
In reality you probably have to handle different types of errors rather than simply panic though. Still it makes the logic more clear than exceptions, and likely more performant.
By convention you should implement Error() interface for contexutal error info:
type FooError struct {
name string
age int
}
func (f *FooError) Error() string {
return f.name + " " + f.age + " " + f.Err.Error()
}
Note variable can't redeclared unless in multiple variables case at least one is new.
func foo() (int, string) {
return 1, "HI"
}
func main() {
fmt.Println(foo()[0])
}
go run: ./test.go:12: multiple-value foo() in single-value context
var array1 [3]int
var array2 = [3]int{1,2,3}
array3 := [...]int{1,2,3}
fmt.Println(array1, array2, array3)
array1 = array2 //array copying
Slices are pointers. Its space is allocated at runtime.
s1 := make([]int, 0, 10)
s2 := []int{}
var array1 = [3]int{1, 2, 3}
slice1 := array1[:3]
slice1[1] = 5 //changes array1
fmt.Println(array1, slice1)
slice1 = append(slice1, 10) //no longer pointing to the original array
slice1[1] = 6
fmt.Println(array1, slice1)
fmt.Printf("%p, %p\n", &array1, &slice1[0])
P = make([][]float64, 100)
for i := 0; i < 100; i++ {
P[i] = make([]float64, 50)
}
type person struct {
name string
age int
}
func updateAge(p person) {
p.age = 25
}
func main() {
p := person{name:"John", age:20}
fmt.Println(p.age)
updateAge(p)
fmt.Println(p.age) //output 20
}
type age int
func (s age) Error() string {
return fmt.Sprintf("Something is wrong %d", s)
}
type foo func(name string) error
func (fn foo) Method(string){
return "HI", nil
}
func main() {
s := age(12)
fmt.Println(s.Error())
}
This is useful when you apply certain functions to your data type (HTTP handler, sort function, etc.)
var x, ok = y.(T) # assert y if of type Tit works if y implements T's interface type.
type Job struct {
Command string
*log.Logger
}
job := Job("job1", log.New(os.Stderr, "Job: ", log.Ldate)})
job.Log("Hello!)
struct Job will forward the method to its embedded struct Logger so the receive will be Logger.
struct Foo {
...
}
func NewFoo() {
foo := Foo{...}
...
return &foo
}