package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
; al final (el compilador los pone solo).package main + func main() = tu int main().#include. import trae paquetes.var x int = 10
y := 20 // inferencia de tipos, esto es lo más común
var nombre string = "Carlos"
const Pi = 3.14159
:= es la forma idiomática. var se usa cuando necesitas el tipo explícito o valor cero.
func dividir(a, b int) (int, int) {
return a / b, a % b
}
func main() {
cociente, resto := dividir(17, 5)
fmt.Println(cociente, resto) // 3 2
}
Esto reemplaza el patrón de C de pasar punteros de salida.
func dividir(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("división por cero")
}
return a / b, nil
}
func main() {
resultado, err := dividir(10, 0)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(resultado)
}
if err != nil es EL patrón en Go. Lo vas a escribir cientos de veces.
func incrementar(x *int) {
*x = *x + 1
}
func main() {
n := 5
incrementar(&n)
fmt.Println(n) // 6
}
Mismo * y &, pero no puedes hacer p++ ni p + 1. Go te protege de eso.
struct de C, sin typedef necesario)type Punto struct {
X, Y int
}
func main() {
p := Punto{X: 3, Y: 4}
fmt.Println(p.X, p.Y)
}
func (p Punto) Distancia() float64 {
return math.Sqrt(float64(p.X*p.X + p.Y*p.Y))
}
func main() {
p := Punto{3, 4}
fmt.Println(p.Distancia()) // 5
}
for// como un for de C
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// como un while de C
i := 0
for i < 5 {
fmt.Println(i)
i++
}
// infinito
for {
break
}
malloc/realloc manejado por el lenguaje)nums := []int{1, 2, 3}
nums = append(nums, 4)
fmt.Println(nums) // [1 2 3 4]
for i, v := range nums {
fmt.Println(i, v) // índice, valor
}
func decir(msg string) {
fmt.Println(msg)
}
func main() {
go decir("en otra goroutine") // como un thread, pero ultra liviano
decir("en main")
}
Esto es como crear un pthread pero sin la ceremonia de pthread_create.
Diferencias clave respecto a C que te van a chocar al principio:
nil existe pero el compilador es más estricto).malloc/free manual.interfaces (comportamiento, no estado).gofmt formatea tu código automáticamente, no hay debate de estilo.Dale, acá tenés los mismos ejemplos pero en C puro, para que compares directo.
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
int x = 10;
int y = 20;
char *nombre = "Carlos";
#define PI 3.14159
En C no hay inferencia de tipos como :=, siempre tenés que declarar el tipo.
void dividir(int a, int b, int *cociente, int *resto) {
*cociente = a / b;
*resto = a % b;
}
int main() {
int q, r;
dividir(17, 5, &q, &r);
printf("%d %d\n", q, r); // 3 2
}
Esto es justo lo que te mencioné: en C usás punteros para “devolver” varios valores; en Go es nativo del lenguaje.
#include <errno.h>
int dividir(int a, int b, int *resultado) {
if (b == 0) {
return -1; // código de error
}
*resultado = a / b;
return 0; // éxito
}
int main() {
int resultado;
if (dividir(10, 0, &resultado) != 0) {
printf("Error: división por cero\n");
return 1;
}
printf("%d\n", resultado);
}
No hay un tipo error como en Go; en C es convención (return -1, errno, etc).
void incrementar(int *x) {
*x = *x + 1;
}
int main() {
int n = 5;
incrementar(&n);
printf("%d\n", n); // 6
}
typedef para evitar escribir struct siempre)typedef struct {
int x, y;
} Punto;
int main() {
Punto p = {.x = 3, .y = 4};
printf("%d %d\n", p.x, p.y);
}
#include <math.h>
double distancia(Punto p) {
return sqrt(p.x * p.x + p.y * p.y);
}
int main() {
Punto p = {3, 4};
printf("%f\n", distancia(p)); // 5.000000
}
C no tiene azúcar sintáctica de p.Distancia(); siempre es distancia(p).
for y while por separado// for
for (int i = 0; i < 5; i++) {
printf("%d\n", i);
}
// while
int i = 0;
while (i < 5) {
printf("%d\n", i);
i++;
}
// infinito
for (;;) {
break;
}
Acá está la diferencia que mencionaste al principio: C te da for Y while como cosas separadas.
#include <stdlib.h>
int main() {
int *nums = malloc(3 * sizeof(int));
nums[0] = 1; nums[1] = 2; nums[2] = 3;
// "append" manual
nums = realloc(nums, 4 * sizeof(int));
nums[3] = 4;
for (int i = 0; i < 4; i++) {
printf("%d %d\n", i, nums[i]);
}
free(nums); // tenés que liberar la memoria vos mismo
}
go func())#include <pthread.h>
#include <stdio.h>
void *decir(void *msg) {
printf("%s\n", (char *)msg);
return NULL;
}
int main() {
pthread_t hilo;
pthread_create(&hilo, NULL, decir, "en otro hilo");
decir("en main");
pthread_join(hilo, NULL); // esperar que termine
}
Lo que más debería saltarte a la vista comparando ambos lados:
malloc/free) — en Go el GC lo hace por vos.for y while separados — en Go es solo for.