Paquete bytes en Go
El paquete bytes en Go proporciona implementaciones eficientes para la manipulación de slices de bytes. Es fundamental para el procesamiento de datos binarios y texto en forma de bytes.
1. Operaciones Básicas
1.1 Comparación y Búsqueda
func ejemplosComparacion() {
// Compare
texto1 := []byte("hello")
texto2 := []byte("world")
resultado := bytes.Compare(texto1, texto2) // -1 porque "hello" < "world"
// Contains
contenido := []byte("Go es un lenguaje increíble")
subcadena := []byte("lenguaje")
contiene := bytes.Contains(contenido, subcadena) // true
// ContainsAny
tieneVocales := bytes.ContainsAny([]byte("hello"), "aeiou") // true
// ContainsRune
tieneLetra := bytes.ContainsRune([]byte("golang"), 'g') // true
// Count
texto := []byte("go go go")
ocurrencias := bytes.Count(texto, []byte("go")) // 3
}
1.2 Prefijos y Sufijos
func ejemplosPrefijosySufijos() {
datos := []byte("archivo.txt")
// HasPrefix
esArchivo := bytes.HasPrefix(datos, []byte("arch")) // true
// HasSuffix
esTexto := bytes.HasSuffix(datos, []byte(".txt")) // true
// Ejemplo práctico de validación de archivos
func validarArchivo(nombre []byte, extensionesPermitidas [][]byte) bool {
for _, ext := range extensionesPermitidas {
if bytes.HasSuffix(nombre, ext) {
return true
}
}
return false
}
extensiones := [][]byte{[]byte(".txt"), []byte(".doc"), []byte(".pdf")}
esValido := validarArchivo([]byte("documento.pdf"), extensiones) // true
}
2. Manipulación de Texto
2.1 Transformación de Casos
func ejemplosTransformacion() {
// ToUpper/ToLower
texto := []byte("Hello, World!")
mayusculas := bytes.ToUpper(texto)
minusculas := bytes.ToLower(texto)
// Title
titulo := bytes.Title([]byte("bienvenido a go")) // "Bienvenido A Go"
// Ejemplo práctico de normalización
func normalizarTexto(entrada []byte) []byte {
// Convertir a minúsculas
texto := bytes.ToLower(entrada)
// Eliminar espacios extras
texto = bytes.TrimSpace(texto)
// Reemplazar múltiples espacios por uno solo
texto = bytes.Join(bytes.Fields(texto), []byte(" "))
return texto
}
normalizado := normalizarTexto([]byte(" HOLA Mundo ")) // "hola mundo"
}
2.2 Separación y Unión
func ejemplosSeparacionUnion() {
// Split
csv := []byte("id,nombre,edad")
campos := bytes.Split(csv, []byte(","))
// Fields
texto := []byte(" go es genial ")
palabras := bytes.Fields(texto)
// Join
slices := [][]byte{[]byte("hola"), []byte("mundo")}
unidos := bytes.Join(slices, []byte(" "))
// Ejemplo práctico de procesamiento CSV
func procesarCSV(datos []byte) [][]byte {
lineas := bytes.Split(datos, []byte("\n"))
resultado := make([][]byte, 0, len(lineas))
for _, linea := range lineas {
if len(bytes.TrimSpace(linea)) > 0 {
campos := bytes.Split(linea, []byte(","))
for i := range campos {
campos[i] = bytes.TrimSpace(campos[i])
}
resultado = append(resultado, bytes.Join(campos, []byte(",")))
}
}
return resultado
}
}
3. Buffer
3.1 Operaciones con Buffer
func ejemplosBuffer() {
// Crear y escribir en un buffer
var buf bytes.Buffer
// Escribir bytes
buf.Write([]byte("Hello"))
// Escribir string
buf.WriteString(", ")
// Escribir un byte
buf.WriteByte('W')
// Escribir rune
buf.WriteRune('🌟')
// Leer del buffer
contenido := buf.Bytes()
str := buf.String()
// Reset del buffer
buf.Reset()
// Ejemplo práctico: Constructor de consultas SQL
type SQLBuilder struct {
buffer bytes.Buffer
args []any
}
func (sb *SQLBuilder) Where(condicion string, args ...any) *SQLBuilder {
if sb.buffer.Len() > 0 {
sb.buffer.WriteString(" AND ")
}
sb.buffer.WriteString(condicion)
sb.args = append(sb.args, args...)
return sb
}
query := new(SQLBuilder)
query.Where("edad > ?", 18).Where("activo = ?", true)
}
3.2 Ejemplo Avanzado de Buffer
func ejemploBufferAvanzado() {
// Buffer con capacidad inicial
buf := bytes.NewBuffer(make([]byte, 0, 1024))
// Escribir con formato
fmt.Fprintf(buf, "Usuario: %s, Edad: %d", "Juan", 25)
// Leer línea por línea
for {
linea, err := buf.ReadBytes('\n')
if err == io.EOF {
break
}
// Lógica para procesar línea
}
// Ejemplo práctico: Logger personalizado
type Logger struct {
buffer bytes.Buffer
mu sync.Mutex
}
func (l *Logger) Log(formato string, args ...any) {
l.mu.Lock()
defer l.mu.Unlock()
// Añadir timestamp
l.buffer.WriteString(time.Now().Format(time.RFC3339))
l.buffer.WriteString(" - ")
fmt.Fprintf(&l.buffer, formato, args...)
l.buffer.WriteByte('\n')
}
}
4. Casos de Uso Prácticos
4.1 Procesamiento de Archivos
func ejemploProcesamiento() {
// Leer y procesar un archivo por chunks
func procesarArchivoGrande(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
buffer := make([]byte, 4096)
for {
n, err := file.Read(buffer)
if err == io.EOF {
break
}
if err != nil {
return err
}
// Procesar chunk
chunk := buffer[:n]
procesarChunk(chunk)
}
return nil
}
}
4.2 Manipulación de Templates
func ejemploTemplates() {
// Template simple con reemplazo de variables
func reemplazarVariables(template []byte, vars map[string][]byte) []byte {
resultado := make([]byte, len(template))
copy(resultado, template)
for key, value := range vars {
placeholder := []byte("{{" + key + "}}")
resultado = bytes.Replace(resultado, placeholder, value, -1)
}
return resultado
}
template := []byte("Hola {{nombre}}, bienvenido a {{plataforma}}")
vars := map[string][]byte{
"nombre": []byte("Juan"),
"plataforma": []byte("Go"),
}
final := reemplazarVariables(template, vars)
}
5. Optimizaciones y Mejores Prácticas
5.1 Preasignación de Memoria
func ejemplosOptimizacion() {
// Preasignar slice para mejor rendimiento
datos := make([]byte, 0, 1024)
// Usar Builder para concatenaciones eficientes
var builder strings.Builder
builder.Grow(1024) // Preasignar capacidad
// Reutilizar buffers
pool := sync.Pool{
New: func() any {
return bytes.NewBuffer(make([]byte, 0, 4096))
},
}
}
5.2 Procesamiento Concurrente
func ejemplosConcurrencia() {
// Procesar grandes cantidades de datos en paralelo
func procesarDatosParalelo(datos [][]byte, numWorkers int) {
jobs := make(chan []byte, len(datos))
results := make(chan []byte, len(datos))
// Iniciar workers
for i := 0; i < numWorkers; i++ {
go func() {
for data := range jobs {
// Procesar datos
processed := bytes.ToUpper(data)
results <- processed
}
}()
}
// Enviar trabajos
for _, data := range datos {
jobs <- data
}
close(jobs)
// Recolectar resultados
for i := 0; i < len(datos); i++ {
<-results
}
}
}