When I compile the following code, it generates
*syntax error: unexpected case, expecting expression* at line *case workerAddr = <- mr.registerChannel:*
I do not know why it happens since I just want to workerAddr to be set by either channel. Any suggestion will be appreciated.
for i:= 0; i < mr.nMap; i++ {
go func(jobCount) {
for {
var workerAddr string
Select {
// get a worker either from registerChannel or from idle channel
case workerAddr = <- mr.registerChannel:
case workerAddr = <- mr.idleChannel:
}
// omit the following code
}
}(i)
}
It happens because you have written Select when you should have written select.
None of the Go keywords are capitalized, so when the compiler sees a capitalized word, it knows immediately that it's not an expression, and therefore a syntax error.
Related
Background
I'm trying to write a Go library for creating terminal task-lists, inspired by the Node library listr.
My library, golist, prints the task list out in a background goroutine and updates the text and status characters using ANSI escape sequences.
The Problem
There's an issue where the final print of the list will occasionally have extra spaces included, leading to some spaces or repeated lines. Here are two examples – one correct, one not – both from runs of the same exact code (here's a link to the code).
Example
Here's an example of what it should look like:
(Here's a gist of the raw text output for the correct output)
And here's an example of what it sometimes looks like:
(Here's a gist of the raw text output for the incorrect output)
If you look at lines 184 and 185 in the gist of the incorrect version, there are two blank lines that aren't in the correct version.
Why is this happening and why is it only happening sometimes?
Code
I'm printing the list to the terminal in the following loop:
go func() {
defer donePrinting() // Tell the Stop function that we're done printing
ts := l.getTaskStates()
l.print(ts)
for {
select {
case <-ctx.Done(): // Check if the print loop should stop
// Perform a final clear and an optional print depending on `ClearOnComplete`
ts := l.getTaskStates()
if l.ClearOnComplete {
l.clear(ts)
return
}
l.clearThenPrint(ts)
return
case s := <-l.printQ: // Check if there's a message to print
fmt.Fprintln(l.Writer, s)
default: // Otherwise, print the list
ts := l.getTaskStates()
l.clearThenPrint(ts)
l.StatusIndicator.Next()
time.Sleep(l.Delay)
}
}
}()
The list is formatted as a string and then printed. The following function formats the string:
// fmtPrint returns the formatted list of messages
// and statuses, using the supplied TaskStates
func (l *List) fmtPrint(ts []*TaskState) string {
s := make([]string, 0)
for _, t := range ts {
s = append(s, l.formatMessage(t))
}
return strings.Join(s, "\n")
}
and the following function builds the ANSI escape string to clear the lines:
// fmtClear returns a string of ANSI escape characters
// to clear the `n` lines previously printed.
func (l *List) fmtClear(n int) string {
s := "\033[1A" // Move up a line
s += "\033[K" // Clear the line
s += "\r" // Move back to the beginning of the line
return strings.Repeat(s, n)
}
I'm using this site as a reference for the ANSI codes.
Thanks in advance for any suggestions you might have about why this is happening!
Let me know if there's any other information I can add that can help.
I think the ANSI codes are just a red herring. I pulled down the library and tried running it locally, and found that the following section is what is creating this issue:
case s := <-l.printQ: // Check if there's a message to print
fmt.Fprintln(l.Writer, s)
When the printQ channel is getting closed, this case is sometimes running, which seems to be moving the cursor down even though nothing is getting printed. This behaviour went away when I moved the call to close the channel after l.printDone is called.
...
// Wait for the print loop to finish
<-l.printDone
if l.printQ != nil {
close(l.printQ)
}
...
This ensures that the loop is no longer running when the channel is closed, and thus the s := <-l.printQ case cannot run.
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
}
I have written go code which has a for loop, code is given below. but when i build the code i get 'continue is not within loop'. i can't understand why this is happening. Kindly help
Go Version:
go version go1.7.5 linux/amd64
Complete Code at the below link
https://pastebin.com/0ZypMYVK
reference Screenshot
for k:=0;k < len(args);k++{
fmt.Println("k is ", k)
hsCode := args[k]
lenChk:=checkHashLen(hsCode)
if lenChk==false {
fmt.Println("Length should be 32" )
continue
}
codeBytes,_ := json.Marshal(hsCode)
APIstub.PutState(strconv.FormatInt(makeTimestamp(),10), codeBytes)
fmt.Println("Added: ", k)
}
Error
./hashcode.go:88: continue is not in a loop
Your problem is here:
//push single code on the block
func (s *SmartContract) pushCode(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
hsCode := args[0]
lenChk := checkHashLen(hsCode)
if lenChk == false {
fmt.Println("Length should be 32")
continue
}
codeBytes, _ := json.Marshal(hsCode)
APIstub.PutState(strconv.FormatInt(makeTimestamp(), 10), codeBytes)
return shim.Success(nil)
}
The error explains what is going wrong. You're using the keyword continue when not in a for loop, this function doesn't contain a for loop.
initCodeLedger contains a for loop, so you are getting distracted by that, but that's not the line no given in the error which is around line 86/87/88. Ideally post code on play.golang.org if asking a question like this.
The following code generates a syntax error (unexpected ++ at end of statement) in Go 1.6 or 1.7:
package main
import "fmt"
var x int
func increment() int {
return x++ // not allowed
}
func main() {
fmt.Println( increment() )
}
Shouldn't this be permitted?
It's an error, because the ++ and -- in Go are statements, not expressions: Spec: IncDec Statements (and statements have no results that would be returned).
For reasoning, see Go FAQ: Why are ++ and -- statements and not expressions? And why postfix, not prefix?
Without pointer arithmetic, the convenience value of pre- and postfix increment operators drops. By removing them from the expression hierarchy altogether, expression syntax is simplified and the messy issues around order of evaluation of ++ and -- (consider f(i++) and p[i] = q[++i]) are eliminated as well. The simplification is significant. As for postfix vs. prefix, either would work fine but the postfix version is more traditional; insistence on prefix arose with the STL, a library for a language whose name contains, ironically, a postfix increment.
So the code you wrote can only be written as:
func increment() int {
x++
return x
}
And you have to call it without passing anything:
fmt.Println(increment())
Note that we would be tempted to still try to write it in one line using an assignment, e.g.:
func increment() int {
return x += 1 // Compile-time error!
}
But this also doesn't work in Go, because the assignment is also a statement, and thus you get a compile-time error:
syntax error: unexpected += at end of statement
The accepted solution is right that the OP's code does not work because in go increment/decrement(x++/x--) statements are expressions that don't return a value.
However the solution presented has a slightly different effect than the original request.
x++ would return the value of x then increment in C like syntax.
however the opposite would happen if you do it this way:
x++
return x
You can negate that issue by reducing your initial value by one or by using a defer statement as written here:
func incr() int {
defer func() { counter++ }()
return counter
}
https://play.golang.org/p/rOuAv7KFJQw
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."); }