GO é como o fim de um script.
Você pode ter várias instruções CREATE TABLE, separadas por GO. É uma maneira de isolar uma parte do script de outra, mas enviar tudo em um bloco.
BEGIN e END são como { e } em C/++/#, Java, etc.
Eles ligam um bloco lógico de código. Costumo usar BEGIN e END no início e no final de um procedimento armazenado, mas não é estritamente necessário. Onde é necessário é para loops e instruções IF, etc, onde você precisa de mais de uma etapa ...
IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
INSERT INTO Log SELECT @id, 'deleted'
DELETE my_table WHERE id = @id
END