Golang syntax error non declaration statement outside function body

06 Распространенные грамматические ошибки в Go, Русские Блоги, лучший сайт для обмена техническими статьями программиста.

Распространенные грамматические ошибки в Go

1. Открывающие фигурные скобки нельзя размещать на отдельной строке.

код ошибки:

package main

import "fmt"

func main() 
{ 
    fmt.Println("hello world!")
}

Ошибка компиляции:

./main.go:5:6: missing function body for "main"
./main.go:6:1: syntax error: unexpected semicolon or newline before {

Правильный код:

package main

import "fmt"

func main() {
    fmt.Println("hello world!")
}

2. Неиспользуемые переменные

Если у вас есть неиспользуемые локальные переменные, код не скомпилируется.
Если вы присвоите новое значение неиспользуемой переменной, код все равно не скомпилируется. Вам нужно где-то использовать эту переменную, чтобы компилятор успешно компилировался.

код ошибки:

package main

var gvar int

func main() {
    var one int
    two := 2
    var three int
    three = 3
}

Ошибка компиляции:

./main.go:6:6: one declared and not used
./main.go:7:9: two declared and not used
./main.go:8:6: three declared and not used

Правильный код:

package main

import "fmt"

func main() {
    var one int
    _ = one
    two := 2
    fmt.Println(two)
    var three int
    three = 3
    one = three
    var four int
    four = four
}

// Вы также можете закомментировать или удалить неиспользуемые переменные

3. Неиспользованный импорт

Если вы импортируете пакет без использования каких-либо его функций, интерфейсов, структур или переменных, код не скомпилируется.
Если вам действительно нужно импортировать пакет, вы можете добавить знак подчеркивания «_» в качестве имени пакета, чтобы избежать сбоя компиляции. Маркер подчеркивания используется для введения, но не используется.

код ошибки:

package main

import (
    "fmt"
    "log"
    "time"
)

func main() {
}```go

 Ошибка компиляции:

./main.go:4:2: imported and not used: “fmt”
./main.go:5:2: imported and not used: “log”
./main.go:6:2: imported and not used: “time”


 Правильный код:

​```go
package main

import (
    _ "fmt"
    "log"
    "time"
)

var _ = log.Println

func main() {
    _ = time.Now
}

 // Вы также можете удалить или закомментировать неиспользуемый импорт

4. «: =» Простое объявление переменной можно использовать только внутри функции.

код ошибки:

package main

myvar := 1 

func main() {  
}

Ошибка компиляции:

./main.go:3:1: syntax error: non-declaration statement outside function body

Правильный код:

package main

var myvar = 1

func main() {
}

5. Используйте краткие объявления для многократного объявления переменных.

Вы не можете повторно объявлять переменную в одном объявлении, но это разрешено в объявлении с несколькими переменными, где должна быть включена по крайней мере одна новая объявленная переменная.
Повторяющиеся переменные должны находиться в одном блоке кода, иначе вы получите скрытую переменную.

код ошибки:

package main

func main() {
    one := 0
    one := 1
}

Ошибка компиляции:

./main.go:5:6: no new variables on left side of :=

Правильный код:

package main

func main() {
    one := 0
    one, two := 1, 2
    one, two = two, one
}

6. В названии языка Go учитывается регистр.

код ошибки:

package main

import "fmt"

func main() {
    fmt.println("Hello world")
}

// Все следующие коды неверны:
// Package main
// iMport "fmt"
// import "Fmt"
// Func main() {}
// Fmt.Println
// fmt.println

Ошибка компиляции:

./main.go:6:2: cannot refer to unexported name fmt.println
./main.go:6:2: undefined: fmt.println

Правильный код:

package main

import "fmt"

func main() {
    fmt.Println("Hello world")
}

7. Точка с запятой в языке Go.

код ошибки:

package main

import "fmt"

func main() {
    fmt.Println("Hello world") fmt.Println("Hi again")
}

Ошибка компиляции:

./main.go:6:29: syntax error: unexpected fmt at end of statement

Правильный код:

package main

import "fmt"

func main() {
    fmt.Println("Hello world")

    // Чтобы решить вышеуказанные проблемы, вы можете поместить два вышеуказанных оператора в две строки
    fmt.Println("Hi again") 

    // Вы можете заканчивать два оператора точкой с запятой
    fmt.Println("Hello world");fmt.Println("Hi again") 
    test()
}

func test() { 
    // Таким образом, в языке Go точка с запятой может быть сохранена. Если вам необходимо ее использовать, вы можете добавить ее без ошибок.
    fmt.Println("Hello world");fmt.Println("Hi again");
};

8. Недопустимая точка с запятой в языке Go.

код ошибки:

package main

import "fmt";;

func main() {
    fmt.Println("Hello world")
}

Ошибка компиляции:

./main.go:3:14: syntax error: non-declaration statement outside function body

Правильный код:

package main

import "fmt";

func main() {
    fmt.Println("Hello world")
}

9. Обратите внимание на область видимости переменных в языке Go.

код ошибки:

package main

var num int

func main() {
    str := "hello world"
    if true {
        var b bool
    }
    println(num)
    println(str)
    println(b)
}

Ошибка компиляции:

./main.go:12:10: undefined: b

Правильный код:

package main

var num int

func main() {
    str := "hello world"
    if true {
        var b bool
        println(b)
    }
    println(num)
    println(str)
}

10. Случайное скрытие переменной

Синтаксис краткого объявления переменных настолько удобен (особенно для разработчиков, которые использовали динамические языки), что люди легко могут рассматривать его как обычную операцию присваивания. Если вы сделаете эту ошибку в новом блоке кода, ошибок компиляции не будет, но ваше приложение не будет делать то, что вы ожидаете.

package main

import "fmt"

func main() {
    x := 1
    fmt.Println(x) // 1
    {
        fmt.Println(x) // 1
        x := 2
        fmt.Println(x) // 2
    }
    fmt.Println(x) // 1 
}

результат операции:

1
1
2
1

Даже для опытных разработчиков Go это обычная ловушка, но ее трудно обнаружить.

Вы можете использовать команду vet, чтобы найти некоторые из этих проблем. По умолчанию ветеринар не будет выполнять такие проверки, вам нужно установить параметр -shadow:
Команда: go tool vet -shadow your_file.go

go tool vet -shadow main.go
main.go:10: declaration of "x" shadows declaration at main.go:6

11. Без использования явных типов нельзя использовать «nil» для инициализации переменных.

Флаг nil используется для представления «нулевого значения» интерфейсов, функций, карт, срезов и каналов. Если вы не укажете тип переменной, компилятор не сможет скомпилировать ваш код, потому что он не может угадать конкретный тип.

код ошибки:

package main

func main() {
    var x = nil
    _ = x
}

Ошибка компиляции:

./main.go:4:6: use of untyped nil

Правильный код:

package main

func main() {
    var x interface{} = nil
    _ = x
}

12. Используйте нулевые фрагменты и карты.

Добавление элементов в нулевой фрагмент — это нормально, но выполнение того же действия для карты вызовет панику во время выполнения.

Правильный код:

package main

func main() {
    var s []int
    s = append(s, 1)
}

код ошибки:

package main

import (
    "fmt"
)

func main() {
    var m map[int]int
    m[1] = 1
    fmt.Println(m)
}

Ошибка выполнения:

panic: assignment to entry in nil map

Правильный код:

package main

import (
    "fmt"
)

func main() {
    var m map[int]int
    m = make(map[int]int)
    m[1] = 1
    fmt.Println(m)
}

13. Вместимость карты

карта имеет только операцию len, без операции ограничения

код ошибки:

package main

import (
    "fmt"
)

func main() {
    m := map[int]string{1: "a", 2: "b", 3: "c"}
    cap := cap(m)
    fmt.Println(cap)
}

Ошибка компиляции:

./main.go:9:12: invalid argument m (type map[int]string) for cap

Правильный код:

package main

import (
    "fmt"
)

func main() {
    m := map[int]string{1: "a", 2: "b", 3: "c"}
    len := len(m)
    fmt.Println(len)
}

14. Строка не будет нулевой.

Это место, на которое следует обратить внимание разработчиков, которые часто используют nil для выделения строковых переменных.

package main

func main() {
    var x string = nil
    if x == nil {
        x = "default"
    }
}

Ошибка компиляции:

./main.go:4:6: cannot use nil as type string in assignment
./main.go:5:7: invalid operation: x == nil (mismatched types string and nil)

Правильный код:

package main

func main() {
    var x string
    if x == "" {
        x = "default"
    }
}

Variables are containers for storing data values.


Go Variable Types

In Go, there are different types of variables, for example:

  • int— stores integers (whole numbers), such as 123 or -123
  • float32— stores floating point numbers, with decimals, such as 19.99 or -19.99
  • string — stores text, such as «Hello World». String values are surrounded by double quotes
  • bool— stores values with two states: true or false

More about different variable types, will be explained in the Go Data Types chapter.


Declaring (Creating) Variables

In Go, there are two ways to declare a variable:

1. With the var keyword:

Use the var keyword, followed by variable name and type:

Syntax

var variablename type = value

Note: You always have to specify either type
or value (or both).

2. With the := sign:

Use the := sign, followed by the variable value:

Syntax

variablename := value

Note: In this case, the type of the variable is inferred from the value
(means that the compiler decides the type of the variable, based on the value).

Note: It is not possible to declare a variable using
:=, without assigning a value to it.


Variable Declaration With Initial Value

If the value of a variable is known from the start, you can declare the variable and assign a value to it
on one line:

Example

package main
import («fmt»)

func main() {
  var student1 string = «John» //type is
string

  var student2 = «Jane» //type is inferred
  x := 2 //type is inferred

  fmt.Println(student1)
  fmt.Println(student2)
  fmt.Println(x)
}

Try it Yourself »

Note: The variable types of student2 and x is inferred from
their values.



Variable Declaration Without Initial Value

In Go, all variables are initialized. So, if you declare a variable without an initial value,
its value will be set to the default value of its type:

Example

package main
import («fmt»)

func main() {
  var a string
  var b int
  var c bool

  fmt.Println(a)
  fmt.Println(b)
  fmt.Println(c)
}

Try it Yourself »

Example explained

In this example there are 3 variables:

  • a
  • b
  • c

These variables are declared but they have not been assigned initial values.

By running the code, we can see that they already have the default values of their respective types:

  • a is ""
  • b is 0
  • c is false

Value Assignment After Declaration

It is possible to assign a value to a variable after it is declared. This is helpful for cases the value is not initially known.

Example

package main
import («fmt»)

func main() {
  var student1 string
  student1 = «John»
  fmt.Println(student1)
}

Try it Yourself »

Note: It is not possible to declare a variable using «:=» without assigning a value to it.


Difference Between var and :=

There are some small differences between the var var :=:

var :=
Can be used inside and outside of functions Can only be used inside functions
Variable declaration and value assignment can be done separately Variable declaration and value assignment cannot be done separately
(must be done in the same line)

Example

This example shows declaring variables outside of a function, with the var
keyword:

package main
import («fmt»)

var a int
var b int = 2
var c = 3

func main() {
  a = 1
  fmt.Println(a)
  fmt.Println(b)
  fmt.Println(c)
}

Try it Yourself »

Example

Since := is used outside of a function, running the program results in an error.

package main
import («fmt»)

a := 1

func main() {
  fmt.Println(a)

}

Result:


./prog.go:5:1: syntax error: non-declaration statement outside function body

Try it Yourself »


Go Exercises

Синтаксическая ошибка Golang Go: оператор без объявления вне тела функции

Функция makeEvenGenerator должен возвращать функцию, которая последовательно генерирует четные числа:

package main import 'fmt' func makeEvenGenerator() func() uint { i := uint(0) return func() (ret uint) { ret = i i += 2 return } }func main() { nextEven := makeEvenGenerator() fmt.Println(nextEven()) // 0 fmt.Println(nextEven()) // 2 fmt.Println(nextEven()) // 4 } 

При запуске выдает ошибку syntax error: unexpected func, expecting semicolon or newline а также Non-declaration statement outside function body.

Код дословно взят из Введение в программирование на Go пользователя Caleb Doxsey. Я не уверен, в чем проблема.

Вам не хватает новой строки между «}» в конце makeEvenGenerator и «func» в main.

Исправил ошибку и выложил код на площадку.

  • ООО Спасибо. Я не думал, что компилятор заботится о новой строке там, поскольку две части разделены фигурными скобками.

Существуют правила использования точек с запятой.

Спецификация языка программирования Go

Точка с запятой

В формальной грамматике используются точки с запятой «;» в качестве ограничителей в ряде постановок. Программы Go могут опускать большинство этих точек с запятой, используя следующие два правила:

  1. Когда ввод разбивается на токены, точка с запятой автоматически вставляется в поток токенов в конце непустой строки, если последний токен строки является идентификатором целочисленного, с плавающей запятой, воображаемого, рунического или строкового литерала одним из ключевые слова break, continue, fallthrough или возвращают один из операторов и разделителей ++, -,),] или}
  2. Чтобы позволить сложным операторам занимать одну строку, точку с запятой можно опустить перед закрывающими «)» или «}».

Ошибка здесь,

}func main() { 

Напишите,

} func main() { 

Вам не хватало новой строки между } в конце makeEvenGenerator а также func main.

Также альтернативный подход для этого шаблона — использовать канал, не возвращающий функцию:

func evenGenerator() <-chan uint { ch := make(chan uint) go func() { i := uint(0) for { ch <- i i += 2 } }() return ch } func main() { evens := evenGenerator() for i := 0; i < 3; i++ { fmt.Println(<-evens) } } 

детская площадка

  • 1 Это альтернативный подход, а не «обычный подход». Например, в этом случае использование канала приводит к стократному снижению производительности: 3481 нс / операцию по сравнению с 34,4 нс / операцию.
  • @peterSO Хорошее замечание, обновлено. Кстати, скорость канала резко улучшилась: 1,4, 211 нс против 2,23 нс на кончике.

Tweet

Share

Link

Plus

Send

Send

Pin

Понравилась статья? Поделить с друзьями:
  • Golang return error from function
  • Golang printf error
  • Glquake как изменить разрешение
  • Golang print error
  • Glpi http error 500