I am new to Go language and was trying out few examples in GO.
In GO int is not a keyword so I declared a variable with name as int.
package main
import "fmt"
func main() {
var int int = 8
fmt.Println(int)
var number int = 10
fmt.Println(number)
}
Now when I build this code I get following error:
[dev#go test]$ go build variables.go
# command-line-arguments
./variables.go:8: int is not a type
I am trying to understand the reason why this is seen and what did var int int do such that int becomes an unavailable data type.
package main
import "fmt"
func main() {
// int is a predeclared type identifier
var int int = 8
// int is a variable identifier
fmt.Println(int)
// error: int is not a type
var number int = 10
fmt.Println(number)
}
You are shadowing the int identifier.
See The Go Programming Language Specification.
Go is a block structured programming language:
Blocks
Declarations and scope
int is a predeclared identifier and is implicitly declared in the universe block.
The scope of a variable identifier declared inside a function begins at the end of the declaration and ends at the end of the innermost containing block.
The statement
var int int = 8
uses the predeclared int type to declare a variable identifier int, shadowing the predeclared identifier: Variable shadowing.
In Go int is a predefined identifier, therefore it cannot be used as a variable name. So rename the first variable to anything else. Such as num1 and it will compile!
package main
import "fmt"
func main() {
var num1 int = 8
fmt.Println(num1)
var number int = 10
fmt.Println(number)
}
Hope this helps!
Related
Is working example
package main
import "fmt"
func main() {
var newFunc func(int, int) int
newFunc = func(i int, j int) int {
return (i * j)
}
fmt.Println(newFunc(10, 20))
}
But if I taken out the function declaration part, out of main function (as shown below), it fails to compile.. Is mandatory to declare it inside main() function ?
package main
import "fmt"
var newFunc func(int, int) int
newFunc = func(i int, j int) int {
return (i * j)
}
func main() {
fmt.Println(newFunc(10, 20))
}
Compile Err details as follows:
.\functionanonymous1.go:6:1: syntax error: non-declaration statement outside function body
.\functionanonymous1.go:6:15: missing function body
.\functionanonymous1.go:6:33: method has multiple receivers
.\functionanonymous1.go:7:2: syntax error: unexpected return, expecting )
.\functionanonymous1.go:8:1: syntax error: non-declaration statement outside function body
In Go, while declaring variables outside functions, every declaration must begin with a keyword (ie. var). It might be kept in that way so that the parsing is less complicated.
So outside of functions, you can't assign a value to some pre-declared variable (i.e. v = 1 ) and also can't use short variable declarations (i.e. v := 1). You may have noticed that from the error logs, syntax error: non-declaration statement outside function body.
package main
var a int
a = 1 // illegal
b := 1 // illegal
var c = 1 // legal
func main() {}
Updated code:
package main
import "fmt"
var newFunc = func(i int, j int) int {
return (i * j)
}
func main() {
fmt.Println(newFunc(10, 20))
}
Go Playground
Simply, golang doesn't allow that. A variable that declares outside function must contain var.
So you can try:
package main
import "fmt"
var newFunc func(int, int) int = func(i int, j int) int {
return (i * j)
}
func main() {
fmt.Println(newFunc(10, 20))
}
I defined a struct in C like:
struct SomeStruct
{
int var1;
bool var2;
double var3;
int var4[10];
int var5[10][10];
}
struct SomeStruct entity;
And somewhere there was a input box that some user input in GO:
func("entity.var3")
It will return value of entity.var3 in C struct.
Actually I could already implement it in python by cffi and:
def get_one_variable(buffer, setup):
value = buffer
for level in setup:
if isinstance(level, str):
value = getattr(value, level)
else:
[base, extends] = level
value = getattr(value, base)
for extend in extends:
value = value[extend]
return value
Where buffer is python cffi data pointer defined with "FFI.cdef" and setup resolved by:
def parse_variable(self, line):
line = line.replace('\n', '').replace(' ', '')
split = line.split('.')
variable = []
for child in split:
match = self.BASE_EXT_REGEX.match(child)
if match is None:
variable.append(child)
else:
base_name = match.group('base_name')
ext_name = match.group('ext_name')
variable.append([base_name, [int(index) for index in
ext_name.replace('[', ']').replace(']]', ']').strip(']').split(']')]])
return variable
So I can dynamically resolve "entity.var1", "entity.var2", "entity.var3", "entity.var4[0]", "entity.var5[0][1]".
Is there something or someway similar in GO?
This is handled by CGO which is a special package in Go that allows for easy C integration. You can read more about it here and here. Given your examples, a simple CGO example would be:
/*
struct SomeStruct
{
int var1;
bool var2;
double var3;
int var4[10];
int var5[10][10];
}
*/
import "C"
import "fmt"
func main(){
thing := C.struct_SomeStruct{}
thing.var1 = C.int(5)
fmt.Printf("My Struct's var field %d\n",int(thing.var1))
}
Consider this package:
package A
var X="change me"
var Y=func(i int) int { return i*i) }
func Z(i int) int { return -i) }
The two explicit variables (X,Y) can be changed in another package, say main...
package main
import "A"
func main () {
A.X="done"
A.Y=func (i int) int { return i*i*i }
print(A.X,A.Y(7))
//... but A.Z apparently can't be changed.
//A.Z=func (int i) int { return i*i*i } //main.go:8: cannot assign to A.Z
}
Obviously there's a difference between defining a func variable (like Y) and an explicit func (like Z). I have googled this but not found much in the way of enlightenment. It almost seems as if var SomeFunc=func (...) defines indeed a variable, but func SomeFunc(...) defines a constant.
PS: A small goodie I found while researching this which I have not seen mentioned in the Go books I've read so far. A dot before a package import imports names without them having to be qualified:
package main
import . "A"
func main () {
X="done"
Y=func (i int) int { return i*i*i }
print(X,Y(7))
}
func SomeFunc(), in essence creates a strong/constant/immutable binding of the identifier SomeFunc to the function you define. When you create a variable like so:
var (
SomeFunc = func(i int) int {
return i * 2
}
)
You create a global variable of the type func(int) int. You can reassign this variable later on. This is something you can't really do with a func SomeFunc identifier. Simply put, this is because func SomeFunc() binds the function Directly to the identifier. The var SomeFunc approach creates a variable (type func(int) int in this case), and that variable is initialised using the function you're assigning. As is the case with variables: reassignment is possible.
Example
What you can do with functions, is shadow them using a scoped variable. This will probably get flagged by most linters, but it's a technique/trick that sometimes can be useful in testing
Example
As for the dot-imports: Please don't do that unless there's a very, very, very good reason for it. A good reason would be you writing a package that adds to an existing one, so you no longer import an existing one, but import your own. Think of it as extending a package. 99% of the time. Don't, whatever you do, use it to quench errors when you import encoding/json to add json serialization annotations to a struct. In those cases, use an underscore:
package foo
import (
"encoding/json"
)
type Bar struct {
Foobar string `json:"foobar"`
}
func New() *Bar {
&Bar{"Default foobar"}
}
Don't know about golang 1.8, but packages like that could result in compiler errors (package encoding/json imported but not used). To silence that error, you simply changed the import to:
import(
_ "encoding/json"
)
The dot-packages, underscores, and package aliases all follow the same rule: use them as little as possible.
Code used in examples:
package main
import (
"fmt"
)
var (
SomeFunc = func(i int) int {
return i * 2
}
)
func main() {
fmt.Println(SomeFunc(2)) // output 4
reassign()
fmt.Println(SomeFunc(2)) // output 8
shadowReassign()
fmt.Println(SomeFunc(2)) // output 2
}
// global function
func reassign() {
// assign new function to the global var. Function types MUST match
SomeFunc = func(i int) int {
return i * 4
}
}
// assign function to local reassign variable
func shadowReassign() {
reassign := func() {
// same as global reassign
SomeFunc = func(i int) int {
return i
}
}
reassign()
}
There's a difference between declaring a variable initialized with a function value:
var Y=func(i int) int { return i*i) }
and declaring a function:
func Z(i int) int { return -i) }
The specification says this about declarations:
A declaration binds a non-blank identifier to a constant, type, variable, function, label, or package.
The specification also says:
A function declaration binds an identifier, the function name, to a function.
The declaration of Y binds a variable to the name. This variable is initialized with a function value. The declaration of Z binds a function to the name.
If an explicit period (.) appears instead of a name, all the package's exported identifiers declared in that package's package block will be declared in the importing source file's file block and must be accessed without a qualifier.
I have following code for Golang docs parsing. "ts" is ast.TypeSpec. I can check StructType and etc. But, ts.Type is "int". How can I assert for int and other basic type?
ts, ok := d.Decl.(*ast.TypeSpec)
switch ts.Type.(type) {
case *ast.StructType:
fmt.Println("StructType")
case *ast.ArrayType:
fmt.Println("ArrayType")
case *ast.InterfaceType:
fmt.Println("InterfaceType")
case *ast.MapType:
fmt.Println("MapType")
}
The types in the AST represent the syntax used to declare the type and not the actual type. For example:
type t struct { }
var a int // TypeSpec.Type is *ast.Ident
var b struct { } // TypeSpec.Type is *ast.StructType
var c t // TypeSpec.Type is *ast.Ident, but c variable is a struct type
I find it's helpful to print example ASTs when trying to understand how different syntax is represented. Run this program to see an example.
This code will check for ints in most cases, but does not do so reliably:
if id, ok := ts.Type.(*ast.Ident); ok {
if id.Name == "int" {
// it might be an int
}
}
The code is not correct for the following cases:
type myint int
var a myint // the underlying type of a is int, but it's not declared as int
type int anotherType
var b int // b is anotherType, not the predeclared int type
To reliably find the actual types in the source, use the go/types package. A tutorial on the package is available.
In C you can put function pointers into an array of void pointers and convert them back to function pointers of any type:
extern int (*fn1)(void);
extern void (*fn2)(int);
void foo(void)
{
void *array[2];
int i;
/* implicit cast from function pointer to void pointer */
array[0] = fn1;
array[1] = fn2;
for (i = 0; i < 2; i++)
{
int (*fp)(int, int, int);
/* implicit cast from void pointer to function pointer */
fp = array[i];
/* call function with a different signature */
fp(1, 2, 3);
}
}
I need to do the same in Go, using unsafe.Pointers. The questions are:
Can a Go function pointer be converted to an unsafe.Pointer?
Can an unsafe.Pointer be converted to a Go function pointer of a different (or the same) type as the original function pointer?
(The question is not why or whether I need to do that; in the given situation it is okay to call a function with the wrong set of parameters and to misinterpret the return value because the caller and the callees are able to deal with that.)
As LinearZoetrope's answer shows, you can do this. Beware that you can do bad things:
package main
import (
"fmt"
"unsafe"
)
func main() {
f1 := func(s string) {}
f2 := func(i int) int { return i + 1 }
pointers := []unsafe.Pointer{
unsafe.Pointer(&f1),
unsafe.Pointer(&f2),
}
f3 := (*func(int) bool)(pointers[1]) // note, not int
fmt.Println((*f3)(1))
}
playground
It appears to work:
package main
import (
"fmt"
"unsafe"
"math"
)
func main() {
fn := print
faked := *(*func(float64))(unsafe.Pointer(&fn))
faked(1.0)
// For comparison
num := math.Float64bits(1.0)
print(num)
}
func print(a uint64) {
fmt.Println(a)
}
Will print
4607182418800017408
4607182418800017408
Of course, you're probably well aware of the potential problems with trying this.