What is the problem of Go in this context syntactically? [duplicate] - go

This question already has answers here:
How to break a long line of code in Golang?
(6 answers)
Closed 9 months ago.
I was trying to write a function but the issue here surprised me.
userGroup.Use(
middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
if username == "joe" && password == "123"{
return true, nil
}
return false, nil
}) // <- error happens here
)
userGroup.Use(
middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
if username == "joe" && password == "123"{
return true, nil
}
return false, nil
})) // <- !!
Spent an hour for a bug but turns out the last closing parentheses must not float around. Is this an issue with semicolons, commas or indentation?
I remember JS not caring about this kind of stuff
The error I was getting was :
missing ',' before newline in argument list |syntax

This is the result of Golang's semi-colon rule: https://go.dev/doc/effective_go#semicolons, where Go is adding a semicolon as it scans the source, so the original source is free of semicolon.
Following the rule "if the newline comes after a token that could end a statement, insert a semicolon", your earlier code would look like below:
userGroup.Use(
middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
if username == "joe" && password == "123"{
return true, nil
}
return false, nil
}); // <- semicolon added here
)
which of course wrong and causes an error. Moving the closing parentheses on that line instead fixes that.

Related

Is it possible to conditionally implement the comma ok idiom in go, like map lookup? [duplicate]

This question already has answers here:
Return map like 'ok' in Golang on normal functions
(2 answers)
Closed 6 months ago.
In golang, you can fetch a key from a map using the obvious syntax:
someMap := map[string]string{
//... contents
}
value := someMap["key1"]
// If "key1" exists in someMap, then the value will be returned; else empty string.
Problem: You can't tell missing keys apart from legitimate empty string values
So, you can test for presence using the comma ok idiom
value, ok := someMap["key1"]
if ok {
// we know that "key1" was in the map, even if value is empty string
} else {
// we know that "key1" was NOT in the map
}
What this looks like is that there are two different overloads of the map lookup method, one which returns just a single map value result, and one which returns the (value, bool) result, and the compiler seems to be selecting the overload based on how many return values you've said you'd like to receive.
This is quite nice, and I was wondering if it was possible to implement this on my own functions?
E.g:
func fetchValue() (string, bool) {
return "", true
}
func testMain() {
// This works fine, as expected
val, ok := fetchValue()
if ok {
fmt.Println(val)
}
// COMPILE ERROR: Assignment count mismatch: 1 = 2.
val2 := fetchValue()
}
// COMPILE ERROR: fetchValue redeclared in this package
func fetchValue() string {
return ""
}
Is this possible? or is it secret special language sauce that only works for the builtin map type and nothing else?
You cannot define your own function that sometimes returns 2 values, sometimes 1.
You can do:
val, ok := fetchValue()
if !ok {
// failure path.
}
or
val, _ := fetchValue()
// not checking for failure.

In Go, how to verify that the data type of an input from the user matches the data type of the code?

I am new to Go.
Currently, I am creating a menu in Go and I want to verify that the data type of the input from the user matches the data type of the variable defined in the code. Part of my code looks like this so far:
package main
import (
"fmt"
"reflect"
)
var option int // The variable is declared outside of the main().
func general_menu() {
fmt.Println(".......................General Menu..................................")
fmt.Println()
fmt.Println("Calculator..........................................................1")
fmt.Println("Linear algebra package..............................................2")
fmt.Println("Language change.....................................................9")
fmt.Println("Exit...............................................................10")
fmt.Println()
fmt.Println("Choose an option from the menu.")
fmt.Println()
fmt.Scan(&option)
fmt.Println()
if (option != 1 && option != 2 && option != 9 && option != 10)||reflect.TypeOf(option)!=int{
fmt.Println("Wrong option input. Please, try again.")
fmt.Println()
general_menu()
}
}
I know that this doens't work this way, and I know that "int" can not be used as part of an "if" condirion.
I would kindly appreciate any suggestions on the proper way to solve this problem.
Thanks.
Edit: I have added more of my code as kindly suggested by the contributors.
Edit: Based on the answer provided, I have tried to implement a function, but the syntax is still not correct:
func check_integers_are_not_string(x int) bool {
change := strconv.Itoa(x)
if change != nil {
return true
} else {
return false
}
} // This function returns a true boolean value if conversion from int to string was possible, meaning that the entered value is a string.
Just read the documentation of Scan - https://pkg.go.dev/fmt#Scan
It returns the number of successfully read arguments and an error. The input is mapped in your case to a variable of type int, so if a user inputs a string it will return 0 and an error. Otherwise it will return 1 and the error should be nil. You can check for that.
n, err := fmt.Scan(&option)
if n != 1 || err != nil {
// print error and go back
}
One common way to do it is to try to make the conversion and see if it succeeds.
optionInt, err := strconv.Atoi(option) // Assuming option is of type string
if err != nil {
log.Printf("String '%s' cannot be converted to type int: %v", option, err)
os.Exit(1)
}
log.Printf(`optionInt is %d.`, optionInt)
This is a good approach if you are only interested in conversion to one type. Otherwise things can quickly get more involved, utilizing constructs such as lexers and parsers, but that would warrant more information on what you are trying to accomplish.

Why is my initialization statement in `if` syntactically incorrect? [duplicate]

Any idea why this struct expression in for loop initializer makes syntax error in compile-time? Pointer to struct works fine in this case but ofc I need local variable like bellow. Thanks for advices!
type Request struct {
id int
line []byte
err error
}
go func() {
for r := Request{}; r.err == nil; r.id++ {
r.line, r.err = input.ReadSlice(0x0a)
channel <- r
}
}()
Simplifying you code:
for r := Request{}; r.err == nil; r.id++ {
r.line, r.err = input.ReadSlice(0x0a)
channel <- r
}
Gives compile time error:
expected boolean or range expression, found simple statement (missing parentheses around composite literal?) (and 1 more errors)
This construct is ambiguous to parse. The opening brace '{' is not obvious whether it is part of a composite literal or the opening brace of the for statement itself (the for block).
You can make it obvious by using parentheses around the composite literal (as the error suggests):
for r := (Request{}); r.err == nil; r.id++ {
r.line, r.err = input.ReadSlice(0x0a)
channel <- r
}

How to check if user input is empty with bufio?

I'm new with Go syntax, just trying to pass an error if the user did not input anything...
[EDIT] I would like the following function to stop running if the user did not input anything, and print a log. My if required && answer == "" statement doesn't seem to work as "You must enter a value." does not log when the user does not input anything.
func QAR(q string, r string, required bool) string {
reader := bufio.NewReader(os.Stdin)
// Print the question
fmt.Printf(q)
answer, _ := reader.ReadString('\n')
// If the answer is empty, return a log
if required && answer == "" {
log.Fatal("You must enter a value.")
// Can I just use return to block it?
return
}
// Print the response with the answer
if r != "" {
fmt.Println(r, answer)
}
return answer
}
The typical pattern in go is to return multiple values, the last of which is an error, if one occurred. So your function signature could look like this:
func QAR(q string, r string, required bool) (string, error)
And the return statements like this:
return "", fmt.Errorf("user provided no input")
// ...
return answer, nil
[EDIT]
Note that bufio.Reader.ReadString(...) includes the delimiter, so you probably need to check if answer == "\n".

unexpected semicolon or newline before else even though there is neither before else if

I'm trying to fix these errors in my golang code and if someone could help me with that, I'd appreciate it.
Here is my code: http://play.golang.org/p/yELWfIdWz5
Although, the one that is troubling me the most is the first one on line 21 where the error says: syntax error: unexpected semicolon or newline before else. I can't find a semicolon or new line on or just before line 21 at all.
Also, what do the errors on line 28 and 32 mean ( non-declaration statement outside function body )-- those statements are in the main() function and the last closing brace closes that function so why is there an error there.
I have a feeling that all of these errors are due to the first one.
I'd greatly appreciate any and all help in resolving these or at least learning more about them.
Here is the code:
package main
import "fmt"
func main() {
var current_mid = ""
current_topic := make(map[string][]string)
f, err := os.Open(*inputFile)
if err != nil {
fmt.Println(err)
return
}
r := bufio.NewReader(f)
xmlFile, _ := os.Create("freebase.xml")
line, err := r.ReadString('\n')
for err == nil{
subject, predicate, object := parseTriple(line)
if subject == current_mid{
current_topic[predicate] = append(current_topic[predicate], object)
}
else if len(current_mid) > 0{
processTopic(current_mid, current_topic, xmlFile)
current_topic = make(map[string][]string)
}
current_mid = subject
line, err = r.ReadString('\n')
}
processTopic(current_mid, current_topic, xmlFile)
if err != io.EOF {
fmt.Println(err)
return
}
}
You need to put the 'else' on the line with the close brace in Go.
Go inserts a ; at the end of lines ending in certain tokens including }; see the spec. That means that, fortunately, it can insert the ending semicolon on x := func(){...} or x := []int{1,2,3}, but it also means it inserts one after the } closing your if block. Since if {...} else {...} is a single compound statement, you can't stick a semicolon in the middle of it after the first }, hence the requirement to put } else { on one line
It's unusual, but it keeps the semicolon-insertion behavior simple. Having been hit with unexpected program behavior because of the cleverer semicolon insertion rules in another semicolon-optional language, this seems alright in the scheme of things.
And I can see how the error message was confusing, but 'newline before else' just refers to the newline after the } on the previous line.
https://golang.org/doc/effective_go.html#if
You can find the explanation here, but I find it to be a bit bikeshedding. For example, this, unintuitive as it is, compiles:
if your_age >= 16 {
say("\n You can earn a Drivers License."); } else
if your_age >= 18 { say("\n You can vote."); } else
{ say("\n You can have fun."); }

Resources