Sintaxis básica
La sintaxis básica de Go es muy simple y fácil de entender, comencemos con un ejemplo muy sencillo.
package main
import "fmt"
func main() {
fmt.Println("Hello 世界!")
}La palabra clave
packagedeclara a qué paquete pertenece el archivo go actual, los archivos de entrada deben declararse como paquetemain, la función de entrada es la funciónmain, al nombrar paquetes y funciones personalizados se debe evitar repetirlos.importes la palabra clave de importación, seguida por el nombre del paquete a importar.funces la palabra clave de declaración de función, utilizada para declarar una función.fmt.Println("Hello 世界!")es una sentencia que llama a la funciónPrintlndel paquetefmtpara realizar la salida.
Lo anterior es una introducción simple a la sintaxis, a continuación vamos a entender los conceptos con un poco más de detalle.
Paquetes
En Go, los programas se construyen enlazando paquetes entre sí. La unidad básica de importación en Go es un paquete, no un archivo .go. Un paquete es básicamente una carpeta, en inglés package, dentro del paquete se comparten todas las variables, constantes y todos los tipos definidos. Se recomienda que el estilo de nomenclatura de paquetes sea siempre en minúsculas y lo más breve posible.
Visibilidad
Anteriormente se mencionó que dentro del paquete se comparten todas las variables, constantes y todos los tipos definidos, pero para el exterior del paquete no es así, a veces no quieres que otros accedan a un determinado tipo, por lo que necesitas controlar la visibilidad. Es posible que hayas visto palabras clave como Public, Private en otros lenguajes OOP, sin embargo en Go no existen estas, su forma de controlar la visibilidad es muy simple, las reglas son las siguientes
- Nombres que comienzan con mayúscula, son tipos/variables/constantes públicos
- Nombres que comienzan con minúscula o guión bajo, son tipos/variables/constantes privados
Por ejemplo, en el siguiente ejemplo, la constante MyName es pública, mientras que la constante mySalary es privada.
package example
// Público
const MyName = "jack"
// Privado
const mySalary = 20_000Esta regla de visibilidad se aplica en todo el lenguaje Go.
Importación
Importar un paquete para usar los tipos/métodos/funciones/variables de ese paquete, la sintaxis de importación es import seguido del nombre del paquete
package main
import "example"Cuando se importan múltiples paquetes, puedes escribirlo así
package main
import "example"
import "example1"También se pueden agrupar con paréntesis, el siguiente método es más común en la práctica.
package main
import (
"example"
"example1"
)Si hay nombres de paquetes duplicados, o el nombre del paquete es complejo, también puedes asignarles alias
package main
import (
e "example"
e1 "example1"
)Cuando el alias es un guión bajo _ es una importación anónima, los paquetes importados anónimamente no pueden ser utilizados, esto se hace generalmente para cargar la función init del paquete, pero sin necesidad de usar los tipos del paquete, un ejemplo común es registrar el driver de base de datos, pero no necesitas usar el driver manualmente.
package main
import (
e "example"
_ "mysql-driver-go"
)Después de importar, cuando quieras acceder a los tipos del paquete, puedes hacerlo mediante nombrePaquete.identificador, por ejemplo en el siguiente ejemplo, si intentas acceder a un tipo privado, el compilador te dirá que no se puede acceder.
package main
import (
"example"
"fmt"
)
func main() {
fmt.Println(example.MyName)
}Hay una forma especial de importación que importa todos los tipos del paquete al ámbito del paquete actual, los tipos importados de esta manera ya no necesitan el operador . para acceder, pero si hay tipos con el mismo nombre no se podrá compilar.
package main
import (
. "example"
)WARNING

En Go no se pueden realizar importaciones circulares, ya sean directas o indirectas. Por ejemplo, si el paquete A importa el paquete B, y el paquete B también importa el paquete A, esto es una importación circular directa. Si el paquete A importa el paquete C, el paquete C importa el paquete B, y el paquete B importa el paquete A, esto es una importación circular indirecta. Si existe una importación circular, no se podrá compilar.
Paquete interno
En Go se convenciona que un paquete llamado internal dentro de un paquete es un paquete interno, los paquetes externos no podrán acceder a ningún contenido del paquete interno, de lo contrario no compilará, veamos un ejemplo.
/home/user/go/
src/
crash/
bang/ (go code in package bang)
b.go
foo/ (go code in package foo)
f.go
bar/ (go code in package bar)
x.go
internal/
baz/ (go code in package baz)
z.go
quux/ (go code in package main)
y.goPor la estructura de archivos se puede ver que el paquete crash no puede acceder a los tipos del paquete baz.
Comentarios
Go soporta comentarios de una línea y comentarios de múltiples líneas, se recomienda dejar un espacio entre el comentario y el contenido, por ejemplo
// Este es el paquete main
package main
// Se importó el paquete fmt
import "fmt"
/*
*
Esta es la función de inicio main
*/
func main() {
// Esta es una sentencia
fmt.Println("Hello 世界!")
}Identificadores
Un identificador es un nombre, utilizado para nombrar paquetes, funciones, variables, etc., las reglas de nomenclatura son las siguientes
- Solo puede estar compuesto por letras, números y guiones bajos
- Solo puede comenzar con una letra o guión bajo
- Distingue estrictamente entre mayúsculas y minúsculas
- No puede repetirse con ningún identificador existente, es decir, debe ser único dentro del paquete
- No puede entrar en conflicto con ninguna palabra clave incorporada de Go
A continuación se listan todas las palabras clave incorporadas, también puedes ir a Manual de referencia-Identificadores para ver más detalles
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return varOperadores
A continuación se muestra la prioridad de los operadores soportados en Go, también puedes ir a Manual de referencia-Operadores para ver más detalles.
Precedence Operator
5 * / % << >> & &^
4 + - | ^
3 == != < <= > >=
2 &&
1 ||Hay un punto a tener en cuenta, Go no eligió usar ~ como operador de negación a nivel de bits, sino que reutilizó el símbolo ^, cuando se usa ^ con dos números, por ejemplo a^b, es el operador XOR, cuando se usa con un solo número, por ejemplo ^a, entonces es el operador de negación a nivel de bits. Go también soporta operadores de asignación aumentada, como se muestra a continuación.
a += 1
a /= 2
a &^= 2TIP
En Go no existen los operadores de incremento y decremento, han sido degradados a sentencias statement, y se establece que solo pueden estar después del operando, así que no hay que preocuparse por cuestiones como i++ y ++i.
a++ // correcto
++a // incorrecto
a-- // correctoOtro punto es que ya no tienen valor de retorno, por lo que escribir sentencias como a = b++ es incorrecto.
Literales
Los literales, en términos de informática, son símbolos utilizados para expresar un valor fijo en el código fuente, también llamados valores literales. Ambos términos significan lo mismo, lo que escribas, ese será el valor, el valor es "literalmente" lo que está escrito.
Literales enteros
Para facilitar la lectura, se permite usar el guión bajo _ para separar números, pero solo se permite usar después del símbolo de prefijo y entre los dígitos.
24 // 24
024 // 24
2_4 // 24
0_2_4 // 24
10_000 // 10k
100_000 // 100k
0O24 // 20
0b00 // 0
0x00 // 0
0x0_0 // 0Literales de punto flotante
Mediante diferentes prefijos se pueden expresar números de punto flotante en diferentes bases
0.
72.40
072.40 // == 72.40
2.71828
1.e+0
6.67428e-11
1E6
.25
.12345E+5
1_5. // == 15.0
0.15e+0_2 // == 15.0
0x1p-2 // == 0.25
0x2.p10 // == 2048.0
0x1.Fp+0 // == 1.9375
0X.8p-0 // == 0.5
0X_1FFFP-16 // == 0.1249847412109375
0x15e-2 // == 0x15e - 2 (integer subtraction)Literales de números complejos
0i
0123i // == 123i
0o123i // == 0o123 * 1i == 83i
0xabci // == 0xabc * 1i == 2748i
0.i
2.71828i
1.e+0i
6.67428e-11i
1E6i
.25i
.12345E+5i
0x1p-2i // == 0x1p-2 * 1i == 0.25iLiterales de caracteres
Los literales de caracteres deben estar entre comillas simples '', los caracteres en Go son completamente compatibles con utf8.
'a'
'ä'
'你'
'\t'
'\000'
'\007'
'\377'
'\x07'
'\xff'
'\u12e4'
'\U00101234'Caracteres de escape
Caracteres de escape disponibles en Go
\a U+0007 carácter de campana
\b U+0008 carácter de retroceso
\f U+000C carácter de avance de página
\n U+000A carácter de nueva línea
\r U+000D carácter de retorno de carro
\t U+0009 carácter de tabulación horizontal
\v U+000B carácter de tabulación vertical
\\ U+005C escape de barra invertida
\' U+0027 escape de comilla simple (solo válido dentro de caracteres)
\" U+0022 escape de comilla doble (solo válido dentro de cadenas)Literales de cadenas
Los literales de cadenas deben estar entre comillas dobles "" o entre comillas invertidas `` (las cadenas con comillas invertidas no permiten escape)
`abc` // "abc"
`\n
\n` // "\\n\n\\n"
"\n"
"\"" // `"`
"Hello, world!\n"
"今天天气不错"
"日本語"
"\u65e5本\U00008a9e"
"\xff\u00FF"Funciones
En Go, la forma de declarar funciones se realiza mediante la palabra clave func, similar a la mayoría de los lenguajes
func main() {
println(1)
}Sin embargo, las funciones en Go tienen dos diferencias, la primera es que el tipo de parámetro va después, como se muestra a continuación
func Hello(name string) {
fmt.Println(name)
}La segunda diferencia es que pueden tener múltiples valores de retorno, y pueden tener nombres
func Pos() () (x, y float64) {
...
}Estilo
En cuanto al estilo de codificación, Go obliga a todos a unificar un mismo estilo, Go oficialmente proporciona una herramienta de formateo gofmt, que se puede usar mediante la línea de comandos, esta herramienta de formateo no tiene ningún parámetro de formateo que se pueda pasar, los únicos dos parámetros solo muestran el proceso de formateo, por lo que no admite personalización, lo que significa que todo el código formateado por esta herramienta tendrá el mismo estilo de código, esto reducirá enormemente la carga mental de los mantenedores, así que en este aspecto buscar la individualidad no es una elección muy sabia.
A continuación se enumerarán algunas reglas simples, también se puede prestar un poco de atención al escribir código.
Llaves de función en nueva línea
Sobre si las llaves después de una función deberían ir en una nueva línea, casi todos los programadores pueden dar sus propias razones, en Go todas las llaves no deberían ir en una nueva línea
// Ejemplo correcto
func main() {
fmt.Println("Hello 世界!")
}Si realmente lo haces así, como se muestra a continuación
// Ejemplo incorrecto
func main()
{
fmt.Println("Hello 世界!")
}Este código ni siquiera compilará, por lo que Go obliga a todos los programadores a no poner las llaves en una nueva línea después de la función.
Sangría de código
Go por defecto usa Tab, es decir, el carácter de tabulación para la sangría, solo en algunos casos especiales se usan espacios.
Espaciado de código
En Go, la mayoría de los espacios tienen significado, hasta cierto punto, esto también representa cómo el compilador ve tu código, por ejemplo en las operaciones matemáticas a continuación
2*9 + 1/3*2Como es sabido, la multiplicación tiene mayor prioridad que la suma, después del formateo, el espacio entre los símbolos * parecerá más compacto, lo que significa que se realiza primero, mientras que el espacio alrededor del símbolo + será mayor, representando que se realiza después.
Omisión de llaves
En otros lenguajes, las sentencias if y for generalmente se pueden abreviar, como se muestra a continuación
for (int i=0; i < 10; i++) printf("%d", i)Pero en Go no, puedes escribir solo una línea, pero debes agregar las llaves
for i := 0; i < 10; i++ {fmt.Println(i)}Expresión ternaria
En Go no existe la expresión ternaria, por lo que el siguiente código no puede compilar
var c = a > b ? a : bA través de este artículo puedes tener un conocimiento preliminar de la sintaxis de Go, en los siguientes contenidos se desarrollará con más detalle.
