Sei sulla pagina 1di 39

CAPTULO 1. INFLUENCIAS DEL LENGUAJE, DOMINIOS DE APLICACIN, MTODOS DE IMPLEMENTACIN, ENTORNOS DE PROGRAMACIN EXISTENTES. EVALUACIN DEL LENGUAJE.

Influencias del lenguaje


Go fue pensado desde su pre-diseo como un lenguaje que asume entornos de multiprocesadores y multi-ncleos, y aplicaciones de redes altamente concurrentes, ofrece el poder de lenguajes de alto nivel como c++/c (que se utilizan para crear sistemas operativos drivers) pero con las facilidades de lenguajes dinmicos como Python o entornos como Javascript. Tiene un nivel de complejidad similar a Java, pero con una filosofa de desarrollo similar a Javascript o Ruby, lo que incluye de paso proteccin de punteros en la memoria, y un recolector automtico de referencias de objetos. Se basa en la familia de programacin de C pero con elementos de Python y la familia de Pascal, Modula y Oberon.

Dominios de aplicacin
Go fue diseado originalmente para software de sistemas, sus diseadores dicen que es tambin ideal para aplicaciones web, posee herramientas para la disear compiladores con el mismo lenguaje, en sntesis go fue creado para adapatarse a las distintas necesidades de cmputo actuales y al crecimiento de la tecnologa de los procesadores.

Mtodos de implementacin
Go es un lenguaje de programacin compilado, concurrente, imperativo, estructurado, no orientado a objetos. Gccgo (el compilador de go)posee el front-end de C++ con un analizador sintctico recursivo descendente acoplado al back-end del estndar GCC. El compilador de go est escrito en C usando yacc/bison para el analizador sintctico. Aunque se trata de un nuevo programa, forma parte de la suite del compilador de C de Plan9 y utiliza una variante del mismo gestor para generar ELF/Mach-O/PE binarios. Los responsables de este lenguaje vieron la posibilidad de realizar un compilador propio de este lenguaje escrito en si mismo, pero no lo hicieron debido a las dificultades de bootstraping. El compilador de go (Gccgo) igualmente deja abierta la posibilidad de escribir un compilador en Go ya que en el lenguaje se encuentran disponibles paquetes para implementar un compilador, y las distintas herrmientas como un analizador sintctico, lxico entre otros.

Entornos de desarrollo
*GoIde: Fue desarrollado como un plugin para la plataforma comunitaria IntelliJ IDEA. Es un
esfuerzo por conseguir un IDE completo en el que se pueda desarrollar cdigo Go con la misma facilidad y el flujo como Java en la misma plataforma. Caractersticas -Comentario / Descomentario -El SDK de Go.

-Icono de tipo archivos. -Archivos de aplicacin y genreacin de librerias Go. -Auto completado de nombres de paquetes SDK y / o paquetes de aplicacin local. -Recopilacin de las aplicaciones Go (semntica soportados son similares a los de gobuild) Cdigo basado en el formato gofmt - (slo cuando se llama con Ctrl + Alt + L) -Funcin de autocompletado de nombres -Aadir automticamente una nueva lnea al final del archivo -Fuerza de codificacin UTF-8 para los archivos go -Modulo de tipo Go -Modos de indexacin del SDK de Go -Sistema de compilacin basado en Makefile. Sistemas -Windows -Linux -Mac OS

*LiteIde: Es un IDE simple, multiplataforma y de cdigo abierto.


Caractersticas -Sistema base de tipo MIME. -Administracin del entorno del sistema. -Gestor del constructor del sistem. -Sistema de depuracin simple y abierta Sistemas -Windows -Linux -Mac OS

Evaluacin del lenguaje


-Legibilidad: Es fcil de leer y entender un programa escrito en Go, es intuitivo hasta las operaciones bsicas. -Escritura: Consta de un nmero pequeo de construcciones primitivas y un conjunto consistente de reglas para combinarlas. Un ejemplo de ellos son sus tipo de datos bsicos hasta las interfaces. Implican demasiada ortogonalidad. -Confiabilidad: Soporta el chequeo de tipo en tiempo de compilacin ya que el tipado es esttico. Soporta Aliasing. No soporta manejo de excepciones.

CAPTULO 2. RESPONSABLES.

HISTORIA

DEL

LENGUAJE,

PRINCIPALES

Go es un lenguaje de programacin concurrente y compilado inspirado en la sintaxis de C. Ha sido desarrollado por Google y sus diseadores iniciales son Robert Griesemer, Rob Pike y Ken Thompson. Actualmente slo est disponible para los sistemas operativos Windows, GNU/Linux yMac OS X. Windows i386, amd64, y ARM arquitectura de procesadores

Nombre
Go es un lenguaje de programacin compilado, concurrente, imperativo, estructurado, no orientado a objetos de una manera bastante especial y con recolector de basura que de momento est soportado en diferentes tipos de sistemas UNIX, incluidos Linux, FreeBSD y Mac OS X. Tambin est disponible en Plan 9 puesto que parte del compilador est basado en un trabajo previo sobre el sistema operativo Inferno. Las arquitecturas soportadas son i386, amd64 y ARM. Existe un port no oficial a Microsoft Windows pero es bastante inestable. Actualmente se est trabajando para llevarlo al sistema operativo de Microsoft... Nombres en disputa En el da de la liberacin general del lenguaje, Francis McCabe, desarrollador de The Go! lenguaje de programacin (ntese el signo de exclamacin), pidi un cambio de nombre de lenguaje de Google al lenguaje de Google para evitar la confusin con su lengua. McCabe cre Go! en el ao 2003; sin embargo, an no ha registrado el nombre. El tema fue cerrado por un desarrollador de Google el 12 de octubre de 2010 con el estado personalizado "Lamentable", con un comentario que "hay muchos productos y servicios informticos llamados Go. En los 11 meses transcurridos desde nuestro lanzamiento, se ha producido una confusin mnima de los dos lenguajes"

Entrando en materia
Desde que Go fue anunciado, se gener un inmenso hype a su alrededor. No faltaron los que se apresuraron a bautizarlo como el prximo C ha habido muchos prximos C que se quedaron en promesas la diferencia principal al probar Go en serio es que te deja una sensacin muy placentera que indica que realmente esta vez si podra haber algo de cierto detrs de esa afirmacin. Despus de programar con l algo ms complejo que un Hello World! deja una agradable sensacin y rpidamente se detectan los siguientes elementos en el lenguaje que revelan que detrs de toda la espantajera de fanboyismo y hype hay sustancia: Go usa una sintaxis parecida a C por lo que los programadores que hayan usado dicho lenguaje se sienten muy cmodos con l. Go usa tipado esttico (estatically typed) y es tan eficiente como C. Go tiene muchas de las caractersticas y facilidad de lenguajes dinmicos como Python. An siendo un lenguaje diseado para la programacin de sistemas, provee de un recolector de basura, reflexin y otras capacidades de alto nivel que lo convierten en un lenguaje muy potente. Go no est orientado a objetos por que no existe jerarqua de tipos pero implementa interfaces. Recepcin del lenguaje Versin inicial Go llev a mucha discusin. Michele Simionato, escribi en un artculo para artima.com: Aqu slo quera sealar sobre las opciones de diseo de interfaces y la herencia. Tales ideas no son nuevas y es una lstima que ningn lenguaje popular ha seguido dicha ruta particular

en el espacio de diseo. Espero Ir llegar a ser popular, y si no, espero que estas ideas finalmente entrar en un lenguaje popular, que ya estamos 10 o 20 aos demasiado tarde . Astels Dave Engine Yard escribi: Go es extremadamente fcil de sumergirse en. Hay un nmero mnimo de conceptos lingsticos fundamentales y la sintaxis es limpia y diseada para ser claro y sin ambigedades. Go es todava experimental y sigue siendo un poco spero alrededor de los bordes. Ars Technica entrevist a Rob Pike, uno de los autores del Go, y le pregunt por qu un nuevo lenguaje que se necesitaba. l respondi que: No basta simplemente agregar caractersticas a los lenguajes de programacin existentes, porque a veces usted puede obtener ms en el largo plazo mediante la adopcin de las cosas. Ellos queran empezar de cero y repensar todo. ... [Pero ellos no queran] para desviarse demasiado de lo que los desarrolladores ya lo saba porque queran evitar alienar a la audiencia de Go objetivo. Go estaba en el puesto 15 en el ndice de Programacin Comunitaria TIOBE de popularidad lenguaje de programacin en su primer ao, 2009, [cita requerida] superando lenguas establecidas como Pascal. En marzo de 2012, se ubic 66 en el ndice. Bruce Eckel dijo: La complejidad de C + + (an ms complejidad se ha aadido en el nuevo C + +), y el consiguiente impacto en la productividad, ya no se justifica. Todos los aros que el C + + programador tena que pasar por el fin de utilizar una lengua C-compatible no tienen sentido ya - son slo una prdida de tiempo y esfuerzo. Ahora, Go tiene mucho ms sentido para la clase de problemas que C + + fue pensado originalmente para resolver.

CAPTULO 3. ESTRUCTURA GENERAL DE LA SINTAXIS DEL PROGRAMA.


La sintaxis de Go es muy similar a la sintaxis utilizada en C. A la hora de declarar una variable o un tipo, se realiza de la misma forma que en C, nicamente que se invierte el orden del nombre de la variable y el tipo, quedando este ltimo al final. Adems, hay que aadir una palabra reservada al principio de las declaraciones. Un ejemplo de esto definiendo tres tipos de variables y un tipo Struct puede ser:
var a int // a es un entero var b, c *int // b y c son punteros a enteros var d []int // d es un array de enteros type S struct { a, b int } // S es una estructura //enteros, a y b.

con

dos

atributos

Las estructuras de control del programa tambin son parecidas a las del lenguaje C. Un ejemplo con un if y un for es:
if a == b { fmt.Print("a y b son iguales") }else { fmt.Print("a y b son distintos") } for i = 0; i < 10; i++ { ... }

No son necesarios los parntesis en la comparacin del if o del for, pero siempre son necesarias las llaves, que no pueden ser omitidas. Adems, hay que tener en cuenta que la llave de apertura de un if debe ir en la misma lnea que la sentencia, y que el else tiene que ir emparejado en la misma lnea que el cierre de bloque del if. Ms adelante se ver la estructura correcta. Hay que notar en el cdigo la ausencia del carcter ; como indicativo del final de sentencia. Cuando Go fue creado, los puntos y coma eran obligatorios en todas las instrucciones. Finalmente, se acord que su uso sera opcional, y que sera el propio compilador el que aadira los puntos y coma al final de las sentencias que considerara validas. An as, el uso de puntos y coma en ciertas estructuras es obligatorio. Este esquema sigue las pautas acerca de este tipo de delimitadores del lenguaje BCPL, precursor de B y por lo tanto de C. As pues, resumiendo acerca del uso de los puntos y coma: Son opcionales en todos los programas al final de una sentencia, aunque debern no ponerse. nicamente son obligatorios a la hora de separar los elementos en la clusula de un bucle for o elementos en un if. El compilador introducira automticamente los puntos y coma, por ello no es conveniente ponerlos, al final de una lnea no vaca, si lo ltimo que se encuentra es: o Un identificador o un literal. o Alguna de las palabras reservadas: break, continue, fallthrough o return. o Alguno de los siguientes tokens: ++, , ), ], g. Se pueden poner los puntos y coma para separar instrucciones en una misma lnea, pudiendo ser omitido antes de ) o de g. Go posee nicamente tres tipos bsicos: Nmeros, Booleanos y Cadenas de caracteres.

CAPTULO 4. LOS NOMBRES, LAS ASOCIACIONES, EL CHEQUEO DE TIPO Y EL ALCANCE.


>>Identificadores(nombres)
Los identificadores son case sensitive. Son una secuencia de una o ms letras y dgitos. El primer carcter de un identificador debe ser una letra. La codificacin utilizada para los caracteres es Unicode. Permite por lo tanta nombres en latino, chino, etc. Guin bajo "_" es considerado una letra.

>>Palabras clave
Las siguientes palabras claves son reservados y no debe usarse como identificadores. break case chan const continue default defer else fallthrough for func go goto if import interface map package range return select struct switch type var

>>Chequeo te tipos
Go hace uso de tipado fuerte y esttico

>>Alcance
El alcance de un idenficador declarado, es la extensin del texto fuente en el cual el identificador denota la constante especfica, tipo, variable, funcin o paquete. El alcance en Go se implimenta lexicamente por medio de bloques. - El alcance de un identificador predeclarado es el bloque universar. - El alcance de un identificador denotando una constante, tipo, variable, o funcin (pero no mtodo) declarado en el nivel superior (fuera de cualquir funcin); es el bloque de paquete. - El alcance de un identificador importado de un paquete es el bloque archivo del archivo conteniendo la declaracin import. - El alcance de un identificador denotando un parmetro de funcin o variable resultado es el cuerpo de la funcin.

El alcance de un identificador constante o variable declarado dentro de una funcin empieza empieza al inicio del ConstSpec o VarSpec (ShortVarDecl para declaraciones cortas) y termina al final del bloque contenedor ms profundo. - El alcance de un identificador de tipo dentro de una funcin empieza en el identificador en el TypeSpec y termina al final del bloque contenedor ms interno. >Alcance de etiquetas. Las etiquetas son usadas en las declaraciones de break, continue y goto. Es ilegal definir una etiqueta que no ser utilizada. En contraste con otros identificadores, el alcance de las etiquetas no esta delimitado por un bloque y no entran en conflicto con identificadores que no son etiquetas. El alcance de la etiqueta es el cuerpo de la funcin en la cual est declarada y excluye el cuerpo de cualquier funcin anidada.

CAPTULO 5. LOS TIPOS DE DATOS


Un tipo determina un conjunto de valores y operaciones especficos para valores de ese tipo. Un tipo puede ser especificado por un nombre de tipo o un literal de tipo, los cuales componen un nuevo tipo a partir de tipos previamente declarados. Instancias nombradas de los tipos booleanos, numricos y cadena son predeclarados. Tipo compuestos -array, struct, puntero, funcin, interface, slice, map, y canalespueden ser construidos utilizando literales de tipo. El tipo esttico (o solo tipo) de una variable es el tipo definido por su declaracin. Variables de tipo interface tambin tienen un tipo dinmico distinto, el cual es el tipo del valor almacenado en la variable en tiempo de ejecucin. El tipo dinmico puede variar durante la ejecucin pero es siempre asignable a una variable del tipo esttico de la interface. Para tipos no interface, el tipo dinmico es siempre el tipo esttico. Cada tipo T tiene un tipo subyacente: Si T es un tipo predeclarado o un literal de tipo, el tipo subyacente correspondiente es el mismo T. De otro modo, el tipo subyacente de T es el tipo subyacente del tipo al cual T hace referencia en su declaracin de tipo.

1-Tipos bsicos
1.1- Tipo bool Define el tipo booleano usual, con dos constantes predefinidas que son: true y false. Hay que tener en cuenta, que a diferencia de otros lenguajes, en Go los punteros y los enteros no son booleanos. 1.2- Tipos cadena (string) Un tipo cadena representa un conjunto de valores cadena. Las cadenas se comportan igual que los slice pero son inmutables, una vez creadas, es imposible cambiar su contenido. El tipo predeclarado de cadena es string. Los elementos de una cadena tienen el tipo byte y pueden ser accedidos utilizando la operacin de indexacin usual. Es ilegal tomar la direccin de un elemento; if s[i] es el i-eisimo byte de una cadena, &s[i] es invalido. La longitud de una cadena s puede ser descubierta utilizando la funcin incorporada len. La longitud es una constante de tiempo de compilacin si s es un literal de cadena. 1.3- Tipos numricos Un tipo numrico representa un conjunto de valores integer o de tipo flotante. Los tipos numericos predeclarados de arquitectura independiente son:

Entero sin signo uint8 uint16 uint32 uint64 Enteros sin signo int8 int16 int32

Rango 8-bit integers (0 to 255) 16-bit integers (0 to 65535) 32-bit integers (0 to 4294967295) 64-bit integers 18446744073709551615) Rango 8-bit integers (-128 to 127) 16-bit integers (-32768 to 32767) 32-bit integers 2147483647) (-2147483648 to (0 to

int64

64-bit integers (-9223372036854775808 to 9223372036854775807)

tipos flotantes float32 float64

Rango the set of all IEEE-754 32-bit floating-point numbers the set of all IEEE-754 64-bit floating-point numbers

complex64 complex128

the set of all complex numbers with float32 real and imaginary parts the set of all complex numbers with float64 real and imaginary parts

Tipo byte Byte Rune alias for uint8 alias for int32

Como puede deducirse de las tablas anteriores, el nmero que acompaa a cada nombre de tipo, es el nmero de bits que ocupa en memoria. Asi, se puede observar que los nmeros flotantes no tienen representaciones validas con 8 y 16 bits.

Existe tambin un conjunto de tipos numricos predeclarados con tamaos especficos para su implementacin: uint int either 32 or 64 bits same size as uint

uintptr sirve para almacenar numero enteros lo suficientemente grandes como para necesitar un puntero. Para evitar problemas de portabilidad todos los tipos numricos son distintos excepto byte, el cual es un alias para uint8 y rune, el cual es un alias para int32. Conversiones son requeridas cuando diferentes tipos numricos son utilizados en una expresin o asignacin. Como por ejemplo, int32 e int no son el mismo a pesar de que puedan tener el mismo en una arquitectura particular. Los tipos que no tienen asociado ningn numero, int, int. y float, se representan con un numero de bits igual al ancho de la palabra de la maquina en la que se ha compilado el cdigo.

2-Tipos de datos compuestos


2.1- Array
Un array es una secuencia de numerada de elementos de un solo tipo, llamado el tipo de elemento. El nmero de elementos es llamado longitud y nunca es negativo. La longitud es parte de tipo array y debe ser una expresin constante que evaluada d un valor integer no negativo. La longitud del array puede ser descubierta utilizando la funcin incorporada len(a). Los elementos pueden ser indexados por ndices 0 hasta len(a)-1. Los tipos array son siempre de una dimensin pero pueden ser compuestos por tipos multidimensionales. Los arrays son valores, no punteros implcitos como ocurre en C. De todas formas, se puede obtener la direccin de memoria donde se ha almacenado un array, que podra servir para pasar un array de forma eficiente a una funcin. Veamos un ejemplo:
func f(a [3]int) { fmt.Println(a) } func fp(a *[3]int) { fmt.Println(a) } func main() { var ar [3] int

f(ar) // Pasa una copia de ar fp(&ar) // Pasa un puntero a ar }

La salida del ejemplo anterior sera la siguiente:


[0 0 0] &[0 0 0]

La funcin Println conoce la estructura de un array y cuando detecta uno, lo imprime de forma optima. Los arrays tambin tienen su propio literal, es decir, su forma de representar el valor real de un array. Ejemplo:
[3]int { 1, 2, 3 } // Array de 3 enteros [10]int { 1, 2, 3 } // Array de 10 enteros, los 3 primeros no nulos [...]int { 1, 2, 3 } // Si no queremos contar el numero de elementos // Si no se quieren inicializar todos, // se puede usar el patrn clave:valor

[10]int { 2:1, 3:1, 5:1, 7:1 }

2.2- Slice
Un slice es una referencia a una seccin de un array. Los slices se usan ms comnmente que los arrays. Un slice se declara como un array, nada ms que este no tiene tamao asociado:
var a []int

Para obtener el nmero de elementos que posee un slice, se recurre a la funcin len(), de igual forma que si fuera un array. Un slice puede crearse troceando un array u otro slice.
a = ar[7:9]

De igual forma, un slice se inicializa asignndole un puntero a un array:


a = &ar // Igual que a = ar[0:len(ar)]

Segn un reciente cambio en la sintaxis referente a los slices, no es necesario poner implcitamente los dos valores, de comienzo y fin, sino que poniendo nicamente el valor de comienzo, creara un slice hasta el final del array o slice que est referenciando.
a = ar[0:] // Igual que a = ar[0:len(ar)]

Al igual que los arrays, los slices tienen sus literales correspondientes, que son iguales pero no tienen tamao asociado.
var slice = []int {1, 2, 3, 4, 5}

Lo que esta instruccin hace, es crear un array de longitud 5, y posteriormente crea un slice que referencia el array. Tambin es posible reservar memoria para un slice (y su array correspondiente) con la funcin predefinida make():
var s100 = make([]int, 100) // slice: 100 enteros

En esta ocasin se utiliza make() y no new() porque es necesario construir un slice, no solo reservar la memoria necesaria. Hay que tener en cuenta que make([]int) devuelve []int, mientras que new([]int) devuelve *[]int). La funcin make() se utiliza para slices, maps y para canales de comunicacin. Un slice se refiere a un array asociado, con lo que puede haber elementos ms all del final de un slice que estn presentes en el array. La funcin cap() (capacity) indica el nmero de elementos que el slice puede crecer.
make([]T, length) make([]T, length, capacity)

Una llamada a make asigna un nuevo, array escondido al cual el slice retornado hace referencia. Eso es, ejecutando
make([]T, length, capacity)

produce el mismo slice que asignando un array y partindolo, los siguientes ejemplos producen el mismo slice:
make([]int, 50, 100) new([100]int)[0:50]

Los slices pueden ser utilizados como arrays crecientes. Esto se consigue reservando memoria para un slice con la funcin make() pasndole dos nmeros - longitud y capacidad - y aumentndolo a medida que crezca:
var sl = make([]int, 0, 100) // Len == 0, cap == 100 func appendToSlice(i int, sl []int) []int { if len(sl) == cap(sl) { error(...) } n := len(sl) sl = sl[0:n+1] // Aumentamos el tamao 1 unidad sl[n] = i

return sl }

La longitud de sl siempre ser el nmero de elementos y crecer segn se necesite. Este estilo es mucho ms barato e idiomtico en Go. Los slices son una estructura muy ligera que permiten al programador generarlos y aumentarlos o reducirlos segn su necesidad. Adems, son fciles de pasar de unas funciones a otras, dado que no necesitan una reserva de memoria extra. Hay que recordar que un slice ya es una referencia de por si, y que por lo tanto, el almacenamiento en memoria asociado puede ser modificado. Por poner un ejemplo, las funciones de E/S utilizan slices, no contadores de elementos.

2.3- Maps
Los maps son otro tipo de referencias a otros tipos. Los maps permiten tener un conjunto de elementos ordenados por el par clave:valor, de tal forma que se pueda acceder a un valor concreto dada su clave, o hacer una asociacin rpida entre dos tipos de datos distintos.El valor no inicializado de un map es null. Los operadores de comparacin == y != deben estas definidos completamente para operndos de los tipos de la clave; por lo tanto el tipo de la clave no debe ser una funcin, map, o slice. Si el tipo de la clave es un tipo interface, estos operadores de comparacin deben ser definidos para los valores de clave dinmicos; el fallo causar un run-time panic.
map[string]int map[*T]struct{ x, y float64 } map[string]interface{}

El nmero de elementos de un map es llamado su longitud. Para un map m, puede ser descubierto utilizando la funcin incorporada len(m) y podra cambia durante la ejecucin. Pueden ser agregados elementos durante la ejecucin utilizando asignaciones y recuperados con expresiones de ndice; pueden ser removidos con la funcin incorporada delete. Un nuevo, map vaco es hecho utilizando la funcin incorporada make, la cual toma el tipo del mapa y opcionalmente su capacidad como argumentos:
make(map[string]int) make(map[string]int, 100)

La capacidad inicial no limita su tamao: maps crecer para acomodar el nmero de tems almacenados en ellos, con la excepcin de maps null. Un map null es equivalente a un map vaci excepto que ningn elemento puede ser agregado.

2.4-Struct

Las structs son un tipo de datos que contienen una serie de atributos y permiten crear tipos de datos ms complejos. Su sintaxis es muy comn, y se pueden declarar de dos formas:
var p struct { x, y float } // o de forma mas usual type Punto struct { x, y float } var p Point

Como casi todos los tipos en Go, las structs son valores, y por lo tanto, para lograr crear una referencia o puntero a un valor de tipo struct, se usa el operador new(StructType). En el caso de punteros a estructuras en Go, no existe la notacin ->, sino que Go ya provee la indireccion al programador.
type Point struct { x, y float } var p Point p.x = 7 p.y = 23.4 var pp *Point = new(Point) *pp = p pp.x = Pi // equivalente a (*pp).x

Ya que los structs son valores, se puede construir un struct a cero simplemente declarndolo, tambin se puede realizar reservando su memoria con new().
var p Point // Valor a "cero" pp := new(Point); // Reserva de memoria idiomtica

Al igual que todos los tipos en Go, los structs tambin tienen sus literales correspondientes:
p = Point { 7.2, 8.4 } p = Point { y:8.4, x:7.2 } pp := &Point { 23.4, -1 } // Forma correcta idiomticamente

De la misma forma que ocurra con los arrays, tomando la direccin de un struct literal, da la direccin de un nuevo valor creado. Este ultimo ejemplo es un constructor para *Point. 2.4.1-Exportacin de tipos. Los campos de un struct deben empezar con una letra Mayscula para que sea visible fuera del paquete. As pues, podemos tener las siguientes construcciones de struct: Tipo y atributos privados. Tipo y atributos exportados. type point struct { x, y float } type Point struct { X, Y float }

Tipo exportado con una mezcla de atributos.

type point struct { X, Y float // exportados nombre string // privado }

Incluso es posible tener un tipo privado con campos exportados. 2.4.2-Atributos Annimos Dentro de un struct se pueden declarar atributos, como otro struct, sin darle ningn nombre al campo. Este tipo de atributos son llamados atributos annimos y actan de igual forma que si la struct interna estuviera insertada o embebida en la externa. Este mecanismo permite una manera de derivar algunas o todas tus implementaciones desde cualquier otro tipo o tipos. Ejemplo:
type A struct { ax, ay int } type B struct { A bx, by float }

B acta como si tuviera cuatro campos: ax, ay, bx y by. Es casi como si B hubiera sido declarada con cuatro atributos, dos de tipo int, y otros dos de tipo float. De todas formas, los literales de tipo B, deben ser correctamente declarados:
b := B { A { 1, 2 }, 3.0, 4.0 } fmt.Println( b.ax, b.ay, b.bx, b.by )

Pero todo el tema de los atributos annimos es mucho ms til que una simple interpolacin de los atributos: B tambin tiene el atributo A. Un atributo annimo se parece a un atributo cuyo nombre es su tipo:
b := B { A { 1, 2 }, 3.0, 4.0 } fmt.Println( b.A )

El cdigo anterior imprimira 1 2. Si A es importado de otro paquete, el atributo aun as debe seguir llamndose A:
import "pkg" type C struct { pkg.A }

... c := C { pkg.A{ 1, 2 } } fmt.Println(c.A) // No c.pkg.A

Para terminar, cualquier tipo nombrado, o puntero al mismo, puede ser utilizado como un atributo annimo y puede aparecer en cualquier punto del struct.
type C struct { x float int string } c := C { 3.5, 7, "Hola" } fmt.Println(c.x, c.int, c.string)

2.4.3-Conflictos Pueden darse una serie de conflictos dada la posible derivacin de unos structs en otros. De hecho, la mayora de conflictos vendran dados por tener dos atributos distintos pero con el mismo nombre. Para ello, se aplican las siguientes reglas en caso de que esto suceda: 1. Un atributo externo oculta un atributo interno. Esto da la posibilidad de sobrescribir atributos y mtodos. 2. Si el mismo nombre aparece dos veces en el mismo nivel, se provoca un error si el nombre es usado por el programa. Si no es usado, no hay ningn problema. No existen reglas para resolver dicha ambigedad, con lo que debe ser arreglado. Ejemplo:
type A struct { a int } type B struct { a, b int } type C struct { A; B } var c C

Usando c.a es un error. Lo seria c.A.a o c.B.a? Evidentemente no, ya que son perfectamente accesibles.
type D struct { B; b float } var d D

El uso de d.b es correcto: se accede al float, no a d.B.b. La b interna se puede conseguir accediendo a travs de d.B.b.

2.5-Tipos puntero
Un tipo puntero denota el conjunto de todos los punteros a variables de un tipo dado, llamados el tipo base del puntero. El valor de un puntero no inicializado es null.
*Point *[4]int

2.6- Tipos funcin


Un tipo funcin denota el conjunto de todas las funciones con los mismos parmetros y tipos de resultado. El valor de una variable de tipo funcin no inicializada es null. Dentro de un lista de parmetros o resultados, los nombres deben o estar todos presentes o todos ausentes. Si estn presentes, cada nombre representa un tem (parmetro o resultado) de un tipo especfico; si estn ausentes, cada tipo representa un tem de ese tipo. Listas de parmetros y resultados estn siempre entre parntesis excepto si hay exactamente un resultado sin nombre pueden escritas como un tipo sin parntesis. El parmetro final en la firma de una funcin puede tener un tipo prefijado con ... Una funcin con dicho parmetro es llamada variadic y puede ser invocada con zero o ms argumentos para ese parmetro.
func() func(x int) int func(a, _ int, z float32) bool func(a, b int, z float32) (bool) func(prefix string, values ...int) func(a, b int, z float64, opt ...interface{}) (success bool) func(int, int, float64) (float64, *[]int) func(n int) func(p *T)

2.7- Tipos interface


Un tipo interface especifica un conjunto de mtodos llamado su interface. Una variable de tipo interface puede almacenar un valor de cualquier tipo con un conjunto de mtodos que es un sper conjunto de la interface. Se dice de dicho tipo que "que implementa la interface". El valor de una variable de tipo interface no inicializada es null. Como en todos los conjuntos de mtodos, en un tipo interface, cada mtodo debe tener un nombre nico.
// A simple File interface interface { Read(b Buffer) bool

Write(b Buffer) bool Close() }

Ms de un tipo puede implementar una interface. Por ejemplo, si dos tipos S1 y S2 tienen el conjunto de mtodos
func (p T) Read(b Buffer) bool { return } func (p T) Write(b Buffer) bool { return } func (p T) Close() { }

(donde T representa S1 o S2) entonces la interface File es implementada por S1 y S2, sin importar que otros mtodos S1 y S2 puedan tener o compartir. Un tipo implementa cualquier interface componiendo cualquier subconjunto de sus mtodos y puede por lo tanto implementar varias interfaces distintas. Por ejemplo, todos los tipos implementas la interface empty.
interface{}

Similarmente, considerese esta especificacin de interface, la cual aparece dentro de una declaracin de tipo para definir un interface llamada Lock:
type Lock interface { Lock() Unlock() }

Si S1 y S2 tambin implementan
func (p T) Lock() { } func (p T) Unlock() { }

ellos implementan la interface Lock as como tambin la interface File. Una interface puede utilizar el nombre de un tipo interface T en lugar de una especificacin de mtodo. El efecto, llamado incrustar una interface, es equivalente a enumerar los mtodos de T explcitamente en la interface.
type ReadWrite interface { Read(b Buffer) bool Write(b Buffer) bool } type File interface { ReadWrite // same as enumerating the methods in ReadWrite

Lock Close() }

// same as enumerating the methods in Lock

Un tipo interface T puede no incrustarse as misma o a cualquier tipo interface que incrusta T, recursivamente
// illegal: Bad cannot embed itself type Bad interface { Bad } // illegal: Bad1 cannot embed itself using Bad2 type Bad1 interface { Bad2 } type Bad2 interface { Bad1 }

2.8- Tipos canales


Un canal provee un mecanismo para que dos funciones ejecutndose concurrentemente se sincronicen y comuniquen por medio del paso de un valor de tipo especfico. El valor de un canal no inicializado es null. El operador <- especifica la direccin del canal, enviar o recibir. Si ninguna direccin es dad, el canal es bidireccional. Un canal puede estar limitado solo para enviar o para recibir por conversin o asignacin.
chan T chan<- float64 <-chan int // can be used to send and receive values of type T // can only be used to send float64s // can only be used to receive ints

El operador <- se asocia con el chan ms a la izquierda posible: chan<- chan int chan<- <-chan int <-chan <-chan int chan (<-chan int) // same as chan<- (chan int) // same as chan<- (<-chan int) // same as <-chan (<-chan int)

Un nuevo, valor de canal inicializado puede ser hecho utilizando la funcin incorporada make, la cual toma el tipo del canal y opcionalmente la capacidad como argumentos:
make(chan int, 100)

La capacidad, en numero de elementos, estable el tamao del buffer en el canal. Si la capacidad es mayor que cero, el canal es asncrono: operaciones de comunicacin son exitosas si el buffer no esta lleno (envos) o no vaci (recibidos), y elementos son recibidos en el orden en que fueron enviados. Si la capacidad es cero u omitida, la comunicacin es exitosa solo cuando ambos, el emisor y receptor estn preparados. Un canal null nunca esta listo para la comunicacin. Un canal puede ser cerrado con la funcin incorporada close; la forma de asignacin multi-valor del operador receptor prueba si un canal ha sido cerrado.

CAPTULO 6. LAS EXPRESIONES Y SENTENCIAS DE ASIGNACIN


>>Expresiones
Una expresin especifica el clculo de una valor por medio de la aplicacin de operadores y funciones a los operandos.

>>Operandos
Los operandos denotan valores elementales en una expresin. Un operando puede ser un literal, un (posiblemente calificado) identificador denotando una constante, variable, o funcin, una expresin de mtodo proporcionando una funcin, o una expresin entre parntesis.

>>Operadores
Operadores combinan operandos en expresiones. Expression = UnaryExpr | Expression binary_op UnaryExpr . UnaryExpr = PrimaryExpr | unary_op UnaryExpr . binary_op rel_op add_op mul_op unary_op = = = = = "||" | "&&" | rel_op | add_op | mul_op . "==" | "!=" | "<" | "<=" | ">" | ">=" . "+" | "-" | "|" | "^" . "*" | "/" | "%" | "<<" | ">>" | "&" | "&^" . "+" | "-" | "!" | "^" | "*" | "&" | "<-" .

Para operadores binarios, los tipos de los operandos deben ser identicos a menos que la operacin implique desplazamientos o constantes sin tipo. Excepto por operaciones de desplazamiento, si un operando es una constante sin tipo y el otro operando no lo es, la constante es convertida al tipo del otro operando. El operando derecho en una expresin de desplazamiento debe ser un interger sin signo o ser una constante sin tipo que pueda ser convertida a un tipo interger sin signo. Si el operando izquierdo de una expresin de desplazamiento no constante es una constante sin tipo, el tipo de la constante es lo que hubiera sido si la expresin de desplazamiento fuese reemplazada solo por su operando izquierdo; el tipo en int si no puede ser determinado del contexto(por ejemplo, si la expresin de desplazamiento es un operando en un comparacin contra una constante sin tipo).
var s uint = 33 var i = 1<<s // 1 tiene tipo int var j int32 = 1<<s // 1 tiene tipo int32; j == 0 var k = uint64(1<<s) // 1 tiene tipo uint64; k == 1<<33 var m int = 1.0<<s // 1.0 tiene tipo int var n = 1.0<<s != 0 // 1.0 tiene tipo int; n == false si ints son tamao 32 bits var o = 1<<s == 2<<s // 1 and 2 tiene tipo int; o == true si ints son tamao 32 bits var p = 1<<s == 1<<33 // ilegal si ints son tamao 32 bits: 1 tiene tipo int, pero 1<<33 desborda int var u = 1.0<<s // ilegal: 1.0 tiene tipo float64, no se puede desplazar var v float32 = 1<<s // ilegal: 1 tiene tipo float32, no se puede desplazar var w int64 = 1.0<<33 // 1.0<<33 es una expresin de desplazamiento de constante

>Operadores aritmticos Los operadores aritmeticos se aplican a valores numericos y producen un resultado del mismo tipo que el primer operando. Los cuatro operadores aritmeticos estandar (+, -, *, /) se aplican a interger, puntos flotantes y tipo complejos, + tambin se aplican a strings. Todos los dems operadores aritmeticos se aplican solo a intergers. + * / % suma diferencia producto cociente resto integers, floats, valores complejos, strings integers, floats, valores complejos integers, floats, valores complejos integers, floats, valores complejos integers

& and por bit integers | or por bit integers ^ xor por bit integers &^ bit clear (and not) integers << despto izquierda >> despto derecha integer << integer sin signo integer >> integer sin signo

Cadenas pueden ser concatenadas usando el operador + o el operador de asignacin += : s := "hi" + string(c) s += " and good bye" La suma de cadenas crea una nueva cadena concatenando lo operandos. >Operadores de comparacin Los operadores de comparacin comparan dos operandos y producen un valor booleano. == != < <= > >= igual no igual menos que menor o igual que mayor que mayor o igual que

En cualquier comparacin, el primero operando debe ser asignable al tipo del segundo operando, o vice versa. Los operadores de igualdad == y != se aplican a operadores que son "comparables" (comparable). Los operdores de orden <, <=, > y >= se aplican a operadores que son "ordenables" (ordered). Estos trminos y resultados de las comparaciones son definidas como siguen: - Valores booleanos son comparables. Dos valores booleanos son iguales si ambos son o true o false. - Valores integer son comparables y ordenados, segn el orden de evaluacin.

Valores de punto flotante son comparables y ordenados, como esta definido por el estndar IEEE-754. - Valores complejos son comparables. Dos valores complejos u y v son iguales si ambos, real(u) == real(v) y imag(u) == imag(v). - Cadenas son comparables y ordenadas, lexicalmente byte por byte. - Punteros son comparables. Dos punteros son iguales si apuntan a la misma variable o si ambos son nulos. Punteros a variables de tamao cero pueden o no ser iguales. - Canales son comparables. Dos canales son iguales si fueron creados por la misma llamada make o si ambos tiene valor nil. - Interfaces son comparables. Dos interfaces son iguales si tienen el mismo tipo dinmico y valores dinmicos iguales o si ambos tienen valor nil. - Un valor x de tipo no interface X y un valor t de tipo interface T, son comparables cuando valores del tipo X son comparables y X implementa T. Ellos son iguales si el tipo dinmico de t es indentico a X y el valor dinmico de t es igual a x. - Structs son comparables si todos sus campos son comparables. Dos structs son iguales si sus correspondientes campos no vacios son iguales. - Arrays son comparables si los valores del tipo de elemento del array son comparables. Dos arrays son iguales si sus correspondientes elementos son iguales. Una comparacin entre dos interfaces con tipo dinmico identico causa un run-time panic si los valores de ese tipo no son comparables. Este comportamientos se aplica no solo a comparaciones directas de valores de interface pero tambin cuando se compara arrays de valores de interface o structs con campos con valores de interface. Valores de slices, maps, y funciones no son comparables. Sin embargo, como caso especial, un valor de slice, map, o funcin puede ser comparado con el identificador predeclarado nil. Comparaciones de valores de punteros, canales, e interfaces a nil tambin es permito y sigue las mismas reglas anteriores. El resultado de una comparacin puede ser asignada a cualquier tipo booleano. Si el contexto no demando un tipo booleano especifico, el resultado tiene el tipo bool.
type MyBool bool var x, y int var ( b1 MyBool = x == y // b2 bool = x == y // b3 = x == y // )

resultado de la comparacin tiene tipo MyBool resultado de la comparacin tiene tipo bool resultado de la comparacin tiene tipo bool

>Operadores lgicos Los operadores lgicos se aplican a valores booleanos y producen un resultado del mismo tipo que los operandos. El operando derecho es evaluado condicionalmente && condicional and p && q es "si p entonces q o sino false" || condicional or p || q es "si p entonces true o sino q" ! negado !p es "negado p"

>Operadores de direcciones Para un operando x de tipo T, la operacin de direccin &x genera un punto de tipo *T a x. El operando debe ser direccionable, eso es, sea ua variable, indireccin de puntero, u

operacin de indexacin de un slice; o un selector de campo de un operando struct direccionable; o una operacin de indexacin de un array direccionable. Como una excepcin al requerimieno de direccionamiento, x tambin debera de un literal compuesto. Para un operando x de puntero tipo *T, la indireccin del puntero *x denota el valor de tipo T apuntado por x. Si x es nil, un intento de evaluar *x causar un run-time panic.
&x &a[f(2)] *p *pf(x)

>Operador de recepcin Para un operando ch de tipo canal, el valor de la operacin de recepcin <-ch es el valor recibido del canal ch. El tipo del valor es el tipo de elemento del canal. La expresin se bloquea hasta que un valor esta disponible. Recibir de un canal nil causa un bloque permanente. Recibir de un canal cerrado siempre es exitoso, inmediatamente retornando el elemento cero del tipo de elemento.
v1 := <-ch v2 = <-ch f(<-ch) <-strobe // espera hasta pulso de reloj y descarta el valor recibido

Una expresin de recepcin usada en una asignacin o inicializacin de la forma


x, ok = <-ch x, ok := <-ch var x, ok = <-ch

produce un resultado adicional booleano reportando si es que la comunicacin fue exitosa. El valor de ok es true si el valor recibido fue entregado por una operacin de envio exitosa al canal, o falso si es generado un valor cero porque el canal esta cerrado o vacio. >Expresiones de mtodo Si M es un conjunto de mtodos de tipo T, T.M es un funcin que puede ser llamada como un funcin regular con los mismos argumentos como M prefijo con un argumento adicional que es el receptor del mtodo. Considere un struct de tipo T con dos mtodos, Mv, el cual su receptor es de tipo T, y Mp, el cual su receptor es de tipo *T.
type T struct { a int } func (tv T) Mv(a int) int { return 0 } func (tp *T) Mp(f float32) float32 { return 1 } var t T

// receptor valor // receptor puntero

La expresin T.Mv produce una funcin equivalente a Mv pero con un receptor explicito como su primer argumento; tiene la firma
func(tv T, a int) int

La funcin puede ser llamada normalmente con un receptor explcito, por lo que estas tres invocaciones son equivalentes:
t.Mv(7) T.Mv(t, 7)

f := T.Mv; f(t, 7)

Similarmente, la expresin (*T).Mp produce un valor de funcin representando Mp con firma func(tp *T, f float32) float32 Para un mtodo con un receptor de valores, uno pude derivar una funcin con un receptor de punteros explicito, entonces
(*T).Mv

produce una valor de funcin representando Mv con la firma


func(tv *T, a int) int

Tal funcin indirecciona a travs del receptor para crear un valor que apruebe como el receptor al mtodo subyacente; el mtodo no sobreescribe el valor cuya direccin es pasada en la llamada a la funcin. El caso final, una funcin con un receptor de valor para un mtodo con receptor de punteros; es ilegal porque mtodos con receptor de punteros no esta en el conjunto de mtodos del tipo del valor. Valores de funcin derivados de mtodos son llamados con la sintaxis de las llamadas a funcin; el receptor es provedo como el primer argumento a la llamada. Eso es, dado f := T.Mv, f es invocado como f(t, 7) no t.f(7). Es legal derivar un valor de funcin de un mtodo de un tipo interface. La funcin resultando toma un receptor explcito del tipo de la interface. >Expresiones constantes Expresiones constantes pueden contener solo operandos constantes y son evaluados en tiempo de compilacin. Constantes booleanas sin tipo, numericas, y cadenas pueden ser usadas como operandos donde sea legal usar operandos de tipo booleano, numerico, o cadena respectivamente. Exceptuando operaciones de desplazamiento, si los operandos de una operacin binaria son diferentes tipos de constantes sin tipo, la operacin y, para operaciones no booleanas, el resultado utiliza el tipo que aparece posteriormente en esta lista: integer, rune, punto flotante, complejo. Por ejemplo, una constante integer sin tipo dividida por una constante compleja sin tipo produce una constante compleja sin tipo. Una comparacin entre constantes siempre produce una constante booleana sin tipo. Si el operando izquierdo de una expresin de desplazamiento constante es una constante sin tipo, de otro modo es una constante del mismo tipo que el operando izquierdo, que debe ser un tipo integer. Aplicando todos los dems operadores a constantes sin tipo resulta en constantes sin tipo del mismo tipo (eso es, una constante booleana, integer, punto flotante, compleja o cadena).
const a = 2 + 3.0 // a == 5.0 (untyped floating-point constant) const b = 15 / 4 // b == 3 (untyped integer constant) const c = 15 / 4.0 // c == 3.75 (untyped floating-point constant) const float64 = 3/2 // == 1.5 (type float64) const d = 1 << 3.0 // d == 8 (untyped integer constant) const e = 1.0 << 3 // e == 8 (untyped integer constant) const f = int32(1) << 33 // f == 0 (type int32) const g = float64(2) >> 1 // ilegal (float64(2) is a typed floating-point constant) const h = "foo" > "bar" // h == true (untyped boolean constant) const j = true // j == true (untyped boolean constant) const k = 'w' + 1 // k == 'x' (untyped rune constant) const l = "hi" // l == "hi" (untyped string constant) const m = string(k) // m == "x" (type string) const = 1 - 0.707i // (untyped complex constant)

const = + 2.0e-4 // const = iota*1i - 1/1i //

(untyped complex constant) (untyped complex constant)

Aplicando la funcin incorporada complex a constantes sin tipo integer, rune, o punto flotante produce una constante sin tipo compleja.
const ic = complex(0, c) // ic == 3.75i (untyped complex constant) const i = complex(0, ) // i == 1.5i (type complex128)

Expresiones constantes siempres son evaluadas exactamente; valores intermedios y las constantes en s puede requerir significativamente ms precisin que la soportada por tipos predeclarados en el lenguaje. Las siguietnes son declaraciones legales:
const Huge = 1 << 100 const Four int8 = Huge >> 98

>>Precedencia de operadores
Los operadores unairos tiene la mayor precedencia. Como los operadores ++ y -forman sentencias, no expresiones, no se encuentras dentro de la jerarqua de operadores. Como consecuencia, la sentencia *p++ es la misma que (*p)++. Hay cinco niveles de precedencia para operadores binarios. Los operadores de multiplicacin tienen la mayor precedencia, seguidos por los operadores de suma, operadores de comparacin, &&(and lgico), y finalmente || (or lgico): Precedencia 5 4 3 2 1 Operador * / % << >> & &^ + - | ^ == != < <= > >= && ||

Operadores binarios de la misma precedencia se asocian de izquierda a derecha. Por ejemplo, x / y * z es lo mismo que (x / y) * z. +x 23 + 3*x[i] x <= f() ^a >> b f() || g() x == y+1 && <-chanPtr > 0

>>Orden de evaluacin
Cuando se evalua los operandos de una expresin, asignacin, o sentencias de retorno, todas las llamadas a funciones, llamadas a mtodos, y operaciones de comunicacin son evaluadas lexicamente de izquierda a derecha. Por ejemplo, en la asignacin
y[f()], ok = g(h(), i()+x[j()], <-c), k()

las llamadas a funciones y comunicaciones ocurren en el orden f(), h(), i(), j(), <-c, g(), and k(). Sin embargo, el orden de esos eventos comparado con la evaluacin e indexado de x y la evaluacion de y no es especificado.
a := 1 f := func() int { a = 2; return 3 } x := []int{a, f()} // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specified

Operaciones de punto flotante dentro de una sola expresin son evaluadas de acuerdo a la asociatividad de los operadores. Parentesis explcitos afectan la evaluacin sobreescribiendo la asociatividad por defecto. En la expresin x + (y + z) la adicin y + z es hecha antes de sumar x.

>>Asignaciones
Cada operando del lado izquierdo debe ser direccionable, una expresin de ndice de un map, o un identificador vacio. Los operandos pueden estar entre parentesis.
x = 1 *p = f() a[i] = 23 (k) = <-ch

// igual que: k = <-ch

Una operacin de asignacin x op= y donde op es una operacin aritmtica es equivalente a x = x op y, pero solo se evalua x una vez. La construccin op= es un nico token. En operaciones de asignacin, ambos, las listas de expresiones del lado izquierdo y derecho deben contener exactamente una expresin de un solo valor.
a[i] <<= 2 i &^= 1<<n

Una asignacin de tuplas asigna los elementos individuales de una operacin de mltiples valores a una lista de variables. Hay dos formas. En la primera, el operando del lado derecho es una expresin de mltiples valores como una evaluacin de funcin o canal u operacin de canal o una asercin de tipo. El nmero de operandos del lado izquierdo debe ser igual al nmero de valores. Por ejemplo, si f es una funcin retornando dos valores: x, y = f() asigna el primer valor para x y el segundo a y. El indenficador vacio provee un mtodo para ignorar valores retornados por una expresin de mltiples valores:
x, _ = f() // ignora el segundo valor retornado por f()

En la segunda forma, el nmero de operandos en el lado izquierdo debe ser igual al nmero de expresiones en la derecha, cada uno de los cuales debe ser de un solo valor, y la nesima expresin en la derecha es asignada al n-esimo operando en la izquierda. La asignacin precede en dos fases. Primero, los operandos de expresiones de indexado e indirecciones de punteros (incluyendo indirecciones de punteros implcitos en selectors) en la izquierda y las expresiones en la derecha son evaluados en el orden usual. Segundo, las asignaciones son realizadas de izquierda a derecha.
a, b = b, a // intercambia a y b

x := []int{1, 2, 3} i := 0 i, x[i] = 1, 2 // establece i = 1, x[0] = 2 i = 0 x[i], i = 2, 1

// establece x[0] = 2, i = 1 // establece x[0] = 1, luego x[0] = 2 (entonces x[0] == 2 al

x[0], x[0] = 1, 2 final) x[1], x[3] = 4, 5

// establece x[1] = 4, luego la configuracin de panic x[3] = 5.

type Point struct { x, y int } var p *Point x[2], p.x = 6, 7 // establece x[2] = 6, luego la configuracin de panic p.x = 7 i = 2 x = []int{3, 5, 7} for i, x[i] = range x { // establece i, x[2] = 0, x[0] break } // luego de este bucle, i == 0 y x == []int{3, 5, 3}

En las asignaciones, cada valor debe ser asignable al tipo de operando al cual es asignado. Si una constante es asignada a una variable de tipo interface, la constante es convertida a un tipo bool, rune, int, float64, complex128 o cadena respectivamente, dependiendo si el valor es una constante booleana, rune, integer, punto flotante, compleja o cadena. >Sentencias de incremento y decremento Las sentencias ++ y -- incrementan o decrementan sus operandos por la constantes sin tipo 1. Como en una asignacin, el operando debe ser direccionable o una expresin de indice de un mapa. Las siguientes sentencias de asignacin son semanticamente equivalentes: Sentencias IncDec x++ x-Asignacin x += 1 x -= 1

CAPTULO 7. LAS SENTENCIAS


Sentencias de control de ejecucin.

>>Sentencias vacas
Las sentencias vacas no hacen nada.

>>Sentencias etiquetadas
Una sentencia etiquetada puede ser el objetico de una sentencia goto, break o continue. Error: log.Panic("error encountered")

>>Sentencias de expresin
Llamadas a funcin, llamadas a mtodos, y operaciones de recepcin pueden aparecer en contexto de sentencia. Estas sentencias deben estar entre parntesis.
h(x+y) f.Close() <-ch (<-ch)

>>Sentencias de envo
Una sentencia de envo enva un valor por un canal. La expresin de canal de ser del tipo canal y el tipo del valor debe ser asignable al tipo del elemento del canal. Ambos, el canal y el valor de la expresin son evaluados antes de que la comunicacin inicie. La comunicacin se bloque hasta que el envo pueda ser realizado. Un envo en un canal sin buffer puede realizarse si es receptor esta listo. Un envo en un canal con buffer puede realizarse si existe lugar en el buffer. Un envo en un canal cerrado causa un run-time panic. Un envo en un canal nil se bloque para siempre.
ch <- 3

>>Sentencias de incremento y decremento


Las sentencias ++ y -- incrementan o decrementan sus operandos por la constantes sin tipo 1. Como en una asignacin, el operando debe ser direccionable o una expresin de ndice de un mapa.

>>Sentencias if
Sentencias "if" especifica la ejecucin condicional de dos ramas de acuerdo al valor de una expresin booleana. Si la expresin se evala a true, la bifurcacin "if" es ejecutada, de otra manera, si esta presente, la bifurcacin "else" es ejecutada. El else debe estar en la misma lnea que la llave de cierre de if.
if x > max {

x = max }

La expresin puede ir precedida por una sentencia simple, que se ejecuta antes de que la evaluacin sea evaluada.
if x := f(); x < y { return x } else if x > z { return z } else { return y }

>>Sentencias switch
Sentencias "switch" proveen varias manera de ejecucin. Una expresin o especificador de tipo es comparado a los "cases" dentro del "switch" para determinar que bifurcacin ejecutar. Hay dos formas: switches de expresin y switches de tipos. En un switch de expresin, los cases contienen expresiones que son comparadas contra los valores de la expresin switch. En un switch de tipo, los casos contienen tipos que son comparados contra los tipos de la expresin switch de notacin especial. Las condiciones no se evaluan en cascada automticamente. Multiples casos que ejecuten una misma secuencia de instrucciones, pueden ser separados por comas.

>Switch de expresiones
switch tag { default: s3() case 0, 1, 2, 3: s1() case 4, 5, 6, 7: s2() } switch x := f(); { case x < 0: return -x default: return x } switch { // expresin switch omitida significa true case x < y: f1() case x < z: f2() case x == 4: f3() }

>Switch de tipo Un swicht de tipo compara tipo en lugar de valores. Por lo dems es igual a un switch de expresin. Esta marcado por una expresin switch especial formada por una asercin de tipo usando la palabra reservada type en lugar del tipo. Los cases luego comparan literales de tipo con los tipos dinmicos de la expresin en la expresin de tipo.
switch i := x.(type) { case nil: printString("x es nil")

case int: printInt(i) // i es un int case float64: printFloat64(i) // i es un float64 case func(int) float64: printFunction(i) // i es una function case bool, string: printString("el tipo es bool o string") default: printString("no se sabe el tipo") }

// i es una interface{}

>>Sentencias for
Una sentencia for especifica la repeticin de ejecucin de un bloque. La iteracin es controlada por una condicin, una clausula "for". En su forma ms simple, una sentencia "for" especifica la ejecucin repetida de un bloque siempre que una condicin booleana evale a true. La condicin es evaluada antes de cada iteracin. Si la condicin es omitida, es equivalente a true.
for a < b { a *= 2 }

Una sentencia for con una clausula for es controlada tambin por su condicin, pero adicionalmente puede especificar una sentencia init y una sentencia post, como una sentencia de asignacin, incremento o decremento. La sentencia init puede ser una declaracin corta de variable, pero la sentencia post no debe de serlo.
for i := 0; i < 10; i++ { f(i) }

Si no esta vacio, la sentencia init es ejecutada una vez antes de evaluar la condicin para la primera iteracin; la sentencia post es ejecutada despus de cada ejecucin del bloque (y solo si el bloque fue ejecutado). Cualquier elemento de la clausula for puede ser omitida pero los punto y comas son requeridos a menos que solo haya una condicin. Si la condicin es omitida, es equivalente a true.
// La falta de condicin implica true (bucle infinito) for ; ; { fmt.Printf("Bucle infinito") } for { fmt.Printf("Bucle infinito, sin poner ;") }

>>Sentencias go
Una sentencia "go" inicia la ejecucin de una llamada de funcin o mtodo como un hilo de control concurrente independiente, o gorutina, dentro del mismo espacio de direccin.
go Expression

La expresin debe ser una funcin. El valor de funcin y parmetros son evaluados de la manera usual en la gorutina llamadora, pero de manera diferente a un llamada regular, la ejecucin del programa no espera a que la funcin invocada termine. En lugar de eso, la funcin se ejecuta independientemente en una nuevo gorutina. Cuando la funcin termina, su gorutina termina. Si la funcin tiene algn valor de retorno, estas son descartadas cuando la funcin se complete.

go Server() go func(ch chan<- bool) { for { sleep(10); ch <- true; }} (c)

>>Sentencias select
Una sentecia select elige de un conjunto de posibilidades que comunicacin se realizar. Su apariencia es similar a una sentencia switch pero con los cases refiriendose a operaciones de comunicacin.
var c, c1, c2, c3 chan int var i1, i2 int select { case i1 = <-c1: print("received ", i1, " from c1\n") case c2 <- i2: print("sent ", i2, " to c2\n") case i3, ok := (<-c3): // same as: i3, ok := <-c3 if ok { print("received ", i3, " from c3\n") } else { print("c3 is closed\n") } default: print("no communication\n") } for { // send random sequence of bits to c select { case c <- 0: // note: no statement, no fallthrough, no folding of cases case c <- 1: }

} select {} // block forever

>>Sentencias break
Una setnencia break termina la ejecucin de la sentencia for, switch o select ms interna. Si hay una etiqueta, debe ser la que este adjuntada a una sentencia for, switch o select, y que sea de aquella cuya ejecucin se termina.
L: for i < n { switch i { case 5: break L } }

>>Sentencias continue
Una sentencia continue inicia la siguiente iteracion del bucle "for" ms interno en su sentencia post. Si hay una etiqueta, debe ser la que este adjuntada a una sentencia for, y que sea de aquella cuya ejecucin se termina.

>>Sentencia fallthrough
Una sentencia fallthrough transfiera el control a la siguiente clausula case en una sentencia switch. Solo puede ser usada como la ultima sentencia no vacia en un case o clausula default en una sentencia de expresin switch.

>>Sentencias return
Una sentencia return termina la ejecucin de la funcin que la contiene y opcionalmente provee un valor o valores al llamador. En una funcin sin un tipo de resultado, una sentencia return no debe especificar ningun valor de retorno.
func noResult() { return }

>Hay tres manera para retornar valores de una funcin con un tipo resultado: -El valor o valores de retorno pueden listarse explicitamente en la sentencia de retorno. Cada expresin debe ser de un solo valor y asignable al correspondiente elemento del tipo resultado de la funcin.
func simpleF() int { return 2 } func complexF1() (re float64, im float64) { return -7.0, -4.0 }

-La lista de expresin en la sentencia de retorno puede ser una sola llamada a una funcin de varios valores. El efecto es como si cada valor retornado de la funcin fuese asignado a una variable temporal con el tipo del correspondiente valor, seguido por una sentencia return listando estas variables, en cuyo punto se aplican las reglas del caso previo.
func complexF2() (re float64, im float64) { return complexF1() }

-La lista de expresiones puede estar vaca si los tipo de retorno de la funcin especifica nombres de sus parmetros resultado. Los parmetro de resultado actan como variables locales ordinarias y la funcin puede asignarles valores segn sea necesario. La sentencia return retorna los valores de estas variables.
func complexF3() (re float64, im float64) { re = 7.0 im = 4.0 return } func (devnull) Write(p []byte) (n int, _ error) { n = len(p) return }

Sin importar la manera en que sean declarados, los valores de resultado son inicializados a los valores cero de sus tipos al iniciarse la funcin.

>>Sentencias goto
Una sentencia goto transfiere el control a la sentencia con la correspondiente etiqueta. goto Error Ejecutar la sentencia goto no debe causar que variables que ya no se encontraban en el alcance del goto entren en el alcance. Por ejemplo:
goto L v := 3 L: // BAD

es errneo porque el salto a la etiqueta L se salta la creacin de v. Una sentencia goto fuera de un bloque no puede saltar a una etiqueta dentro de ese bloque. Por ejemplo:
if n%2 == 1 { goto L1 } for n > 0 { f() n-L1: f() n-}

es errneo porque la etiqueta L1 esta dentro del bloque de la sentencia for, pero el goto no.

PROGRAMAS DE EJEMPLO
Un programa que permita al usuario introducir una cadena de entrada y lue go se imprima
// CADENA-IMPRIMIR package main import ( "bufio" "fmt" "os" ) func main() { Input := os.Stdin in := bufio.NewReader(Input) fmt.Print("Ingrese el texto: ") line, err := in.ReadString('\n') if err == nil { fmt.Print("El texto ingresado fue : ") fmt.Print(line) } }

Un programa de ordenamiento quicksort, el usuario debe indicar el nmero de elementos a ordenar y cargarlos en un vector.
// QUICKSORT-FINAL package main import ( "fmt" ) func rellenar(unarray []int, lalong int) { var cont int for cont = 0; cont < lalong; cont++ { fmt.Println("Introduce el numero para la casilla: ", cont) fmt.Scan(&unarray[cont]) } } func inicializar(unarray []int, lalong int) { var cont int v := unarray for cont = 0; cont < lalong; cont++ { v[cont] = 0 } } func Quicksort(unarray []int, izq int, der int) { var pivote int if izq < der { pivote = pivot(unarray, izq, der) Quicksort(unarray, izq, pivote-1) Quicksort(unarray, pivote+1, der) } } func pivot(unarray []int, izq int, der int) int { var i, pivote, valor_pivote, aux int pivote = izq valor_pivote = unarray[pivote] for i = izq + 1; i <= der; i++ { if unarray[i] < valor_pivote { pivote++ aux = unarray[i] unarray[i] = unarray[pivote] unarray[pivote] = aux } } aux = unarray[izq] unarray[izq] = unarray[pivote]

unarray[pivote] = aux return pivote } func imprimir(unarray []int, lalong int) { var cont int for cont = 0; cont < lalong; cont++ { fmt.Print("En casilla ", cont, " esta el nmero ", unarray[cont], "\n") } } func main() { var tam int fmt.Println(************"Ingrese el tamao del vector a ordenar************") fmt.Scan(&tam) fmt.Println("El tamao del vector a ordenar es de", tam, "elementos") fmt.Println("Ingrese los ", tam, " elemtos") var vector = make([]int, tam) inicializar(vector, tam) rellenar(vector, tam) fmt.Println("El vector ingresado es: ", vector) Quicksort(vector, 0, tam-1) fmt.Println("************El vector ordenado:************") imprimir(vector, tam) }

Un programa de multiplicacin de matrices de tamao definido por el usuario


// MATRIZ-FINAL // /* una matriz de tamao por ejemplo 2*6, 2 filas y 6 * columnas, se representa como un vector que tiene * dos elementos donde cada elemento es un vector * que tiene 6 elementos. * Dos matrices pueden multiplicarse si la columna de la 1era matriz * es igual a la fila de la 2da matriz, ejemplo: A de tamao 2*8 (se lee dos por ocho) y * B de tamao 8*5 (se lee ocho por cinco), dando como resultado una matriz de tamao * 2*5 (dos por cinco) */ package main import ( "fmt" ) /*funcion que carga un vector*/ func cargarVector(v []int, c int, aux int) []int { for i := 0; i < c; i++ { aux = aux + 2 v = append(v, aux) } return v } /*funcion que carga las matrices*/ func cargarMatriz(v []int, f int, c int) [][]int { var a []int var m = make([][]int, f) i := 0 for i = 0; i < f; i++ { a = v[i*c : c*(i+1)] m[i] = a } return m } /*funcion que multiplica las matrices*/ func multiplicarMatriz(m1 [][]int, m2 [][]int, ff1 int, cc1 int, ff2 int, cc2 int) [][]int { //parametros: las dos matrices y las dimensiones de sus respectivas filas y columnas

var suma, f, c, temp int var mn = make([][]int, cc2) //se crea una matriz con la misma cantidad de columnas de la segunda matriz var vect = make([]int, ff1*cc2) f = 0 c = 0 suma = 0 temp = 0 for index := 0; index < ff1*cc2; index++ { for igual := 0; igual < cc1; igual++ { temp = m1[f][igual] * m2[igual][c] suma = suma + temp } vect[index] = suma suma = 0 if c == cc2-1 { f = f + 1 c = 0 } else { c = c + 1 } mn = cargarMatriz(vect, ff1, cc2) } return mn } /*funcion que imprime las matrices*/ func imprimirMatriz(m [][]int, f int) { for i := 0; i < f; i++ { fmt.Print(m[i], " \n") } } /*funcion que imprime los posibles errores*/ func imprimirError(n int) { switch n { case 1: fmt.Println("La matriz no puede tener dimension 0") case 2: fmt.Println("Las matrices no se pueden multiplicar.\n No se cumple la condicion de que la columna de la primera matriz sea igual a la fila de la segunda matriz") } } func main() { var f1, c1, f2, c2, errorNr, cant1, cant2, aux int var vector1 = make([]int, cant1) var vector2 = make([]int, cant2) var matriz2 = make([][]int, f2) var mNueva = make([][]int, f1*c2) errorNr = 0 fmt.Println("Introduzca las dimensiones de la primera matriz:") fmt.Println("cantidad de filas: ") fmt.Scan(&f1) fmt.Println("cantidad de columnas: ") fmt.Scan(&c1) var matriz1 = make([][]int, f1) cant1 = f1 * c1 if cant1 == 0 { errorNr = 1 //1 significa que por lo menos una de las dimensiones es 0 } if errorNr == 0 { fmt.Println("Introduzca las dimensiones de la segunda matriz:") fmt.Println("cantidad de filas: ") fmt.Scan(&f2) fmt.Println("cantidad de columnas: ") fmt.Scan(&c2)

cant2 = f2 * c2 if cant2 == 0 { errorNr = 1 //1 significa que por lo menos una de las dimensiones es 0 } else { fmt.Println("cantidad de filas y columnas de la primera matriz", f1, c1) aux = 0 vector1 = cargarVector(vector1, cant1, aux) //se carga la 1era matriz con numeros pares, empezando con aux+2 matriz1 = cargarMatriz(vector1, f1, c1) aux = 1 fmt.Println("cantidad de filas y columnas de la segunda matriz", f2, c2) vector2 = cargarVector(vector2, cant2, aux) //se carga la 2da matriz con numeros pares, empezando con aux+2 matriz2 = cargarMatriz(vector2, f2, c2) fmt.Println("primera matriz cargada") imprimirMatriz(matriz1, f1) fmt.Println("") fmt.Println("segunda matriz cargada") imprimirMatriz(matriz2, f2) if c1 == f2 { mNueva = multiplicarMatriz(matriz1, matriz2, f1, c1, f2, c2) fmt.Println("Las matrices s se pueden multiplicar") fmt.Println("La matriz resultante es") imprimirMatriz(mNueva, f1) } else { errorNr = 2 } } } imprimirError(errorNr) }

Potrebbero piacerti anche