I'm trying to learn the basics of Go by tweaking examples as I go along the tutorial located here:
http://tour.golang.org/#9
Here's a small function I wrote that just turns ever character to all caps.
package main
import (
"fmt"
"strings"
)
func capitalize(name string) {
name = strings.ToTitle(name)
return
}
func main() {
test := "Sergio"
fmt.Println(capitalize(test))
}
I'm getting this exception:
prog.go:15: capitalize(test) used as value
Any glaring mistakes?
You are missing the return type for capitalize():
package main
import (
"fmt"
"strings"
)
func capitalize(name string) string {
return strings.ToTitle(name)
}
func main() {
test := "Sergio"
fmt.Println(capitalize(test))
}
Playground
Output:
SERGIO
Related
I'm planning to create some method extension for the string type.
I need to write all my extension methods into a separate package.
here is my hierarchy.
root
| main.go
| validation
| validate.go
on the main.go I would like to have, "abcd".Required()
main.go
package main
import (
"fmt"
"./validation"
)
func main() {
fmt.Println( "abcd".Required() )
}
validate.go
package validation
func (s string) Required() bool {
if s != "" {
return true
}
return false
}
When I run it, will get an error.
error
cannot define new methods on non-local type string
I found some answers in other questions on StackOverflow but they don't exactly talk about the string type & having the method in a different package file.
In your validate.go create a new type String:
package validation
type String string
func (s String) Required() bool {
return s != ""
}
And then work with validation.String objects in your main:
package main
import (
"fmt"
"./validation"
)
func main() {
fmt.Println(validation.String("abcd").Required())
}
An executable example with it all in the same file here:
https://play.golang.org/p/z_LcTZ6Qvfn
Problem at reflection, with MethodByName
Code:
package main
import (
"reflect"
"fmt"
)
type test struct {}
var serviceType = map[string]reflect.Value{
"test": reflect.ValueOf(test{}),
}
func (t *test) prnt() {
fmt.Println("test ok")
}
func callFunc(strct string, fName string) {
s := serviceType[strct].MethodByName(fName)
if !s.IsValid(){
fmt.Println("not correct")
return
}
s.Call(make([]reflect.Value,0))
}
func main() {
callFunc("test", "prnt")
}
Output:
not correct
Playground:
https://play.golang.org/p/ZLEQBGYoUOB
Could you help, what I'm doing wrong ?
Two things needs to be corrected.
MethodByName() returns only Exported methods. So you have to rename prnt tp Prnt
Needs to pass a pointer of struct test to reflect.ValueOf() method.
Here is the modified working code https://play.golang.org/p/4MK2kqOz6e2
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
fmt.Print("LOADED!\n")
fmt.Print("insert y value here: ")
inputY := bufio.NewScanner(os.Stdin)
inputY.Scan()
inputXfunc()
}
func inputXfunc() {
fmt.Print("insert x value here: ")
inputX := bufio.NewScanner(os.Stdin)
inputX.Scan()
slope()
}
func slope() {
fmt.Println(inputX.Text())
}
Whenever I run this program, it says, that inputX and inputY are unidentified. How do I make this program use variables that are accessible to all of the functions? All I want to do is devide inputY by inputX then print out the result
I'm just putting my comment as an answer... I would recommend against this however you could just declare the variable at package scope. It would look like this;
package main
import (
"fmt"
"bufio"
"os"
)
var inputX io.Scanner
func main() {
fmt.Print("LOADED!\n")
fmt.Print("insert y value here: ")
inputY := bufio.NewScanner(os.Stdin)
inputY.Scan()
inputXfunc()
}
func inputXfunc() {
fmt.Print("insert x value here: ")
inputX = bufio.NewScanner(os.Stdin) // get rid of assignment initilize short hand here
inputX.Scan()
slope()
}
func slope() {
fmt.Println(inputX.Text())
}
However a better choice would be to change your method definitions to accept arguments and pass the values into them as needed. This would like like so;
func slope(inputX bufio.Scanner) {
fmt.Println(inputX.Text())
}
slope(myInputWhichIsOfTypeIOScanner)
You can create an init() function and make use of it in the main.go by using package like godotenv to set os's environment variables:
global.go file
package global
import (
"log"
"os"
"strconv"
"github.com/joho/godotenv"
)
var (
SERVER_HOST string
SERVER_PORT int
)
func InitConfig() {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
SERVER_HOST = os.Getenv("SERVER_HOST")
SERVER_PORT, _ = strconv.Atoi(os.Getenv("SERVER_PORT"))
}
main.go file
package main
import(
G "path/to/config"
)
func init() {
G.InitConfig()
}
func main() {
G.Init()
}
You will still have to import "G" package in other packages to use the variables, but I think the best way to tackle global variables in Go (or any other languages) is to make use of environment variables.
I'm expecting {"a":"42","b":"78"} from the following code, but it doesn't do it.
package main
import (
"encoding/json"
"fmt"
)
type S struct {
A int `json:"a,string"`
B *int `json:"b,string"`
}
func main() {
var s S
json.Unmarshal([]byte(`{"a":"42","b":"78"}`), &s)
m, _ := json.Marshal(s)
fmt.Println(string(m))
}
Am I doing something wrong?
This is a known issue with 1.3 of the go language.
see https://code.google.com/p/go/issues/detail?id=8587
Given a function, is it possible to get its name? Say:
func foo() {
}
func GetFunctionName(i interface{}) string {
// ...
}
func main() {
// Will print "name: foo"
fmt.Println("name:", GetFunctionName(foo))
}
I was told that runtime.FuncForPC would help, but I failed to understand how to use it.
I found a solution:
package main
import (
"fmt"
"reflect"
"runtime"
)
func foo() {
}
func GetFunctionName(i interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}
func main() {
// This will print "name: main.foo"
fmt.Println("name:", GetFunctionName(foo))
}
Not exactly what you want, because it logs the filename and the line number, but here is how I do it in my Tideland Common Go Library (http://tideland-cgl.googlecode.com/) using the "runtime" package:
// Debug prints a debug information to the log with file and line.
func Debug(format string, a ...interface{}) {
_, file, line, _ := runtime.Caller(1)
info := fmt.Sprintf(format, a...)
log.Printf("[cgl] debug %s:%d %v", file, line, info)
I found a better solution, in this function down here you just simply pass a function and the output is gonna be simple and straight.
package main
import (
"reflect"
"runtime"
"strings"
)
func GetFunctionName(temp interface{}) string {
strs := strings.Split((runtime.FuncForPC(reflect.ValueOf(temp).Pointer()).Name()), ".")
return strs[len(strs)-1]
}
And this is an example of how you use this:
package main
import "fmt"
func main() {
fmt.Println(GetFunctionName(main))
}
And this is the answer you should expect:
main
By getting the function name of the previous caller:
import (
"os"
"runtime"
)
func currentFunction() string {
counter, _, _, success := runtime.Caller(1)
if !success {
println("functionName: runtime.Caller: failed")
os.Exit(1)
}
return runtime.FuncForPC(counter).Name()
}