Comportamiento diferente de len() con valor constante o no constante.
El código a continuación:
const s = "golang.go"
var a byte = 1 << len(s) / 128
El resultado de a
es 4. Sin embargo, después de cambiar const s
a var s
como se muestra a continuación:
var s = "golang.go"
var a byte = 1 << len(s) / 128
Ahora el resultado de a
es 0.
También hay otros códigos de prueba como el siguiente:
const s = "golang.go"
var a byte = 1 << len(s) / 128 // el resultado de a es 4
var b byte = 1 << len(s[:]) / 128 // el resultado de b es 0
var ss = "golang.go"
var aa byte = 1 << len(ss) / 128 // el resultado de aa es 0
var bb byte = 1 << len(ss[:]) / 128 // el resultado de bb es 0
Es extraño que b
sea 0 al evaluar la longitud de s[:]
.
Intento entenderlo según la especificación de Golang:
La expresión len(s) es constante si s es una constante de cadena. Las expresiones len(s) y cap(s) son constantes si el tipo de s es un array o un puntero a un array y la expresión s no contiene recepciones de canal ni llamadas a funciones (no constantes).
Pero no lo consigo. ¿Podría alguien explicármelo de manera más clara?
davy.ai
Parece que el problema tiene que ver con el uso de cadenas constantes frente a variables en combinación con el operador de desplazamiento de bits.
En el primer ejemplo,
const s = "golang.go"
es una cadena constante, por lo que la expresiónlen(s)
también es una constante. Por lo tanto, al realizar1 << len(s) / 128
, se realiza primero la operación de división, lo que resulta enlen(s) / 128 = 1
, luego se realiza la operación de desplazamiento de bits, lo que resulta en1 << 1 = 2
, que luego se convierte al tipobyte
y se asigna aa
. Sin embargo, es importante tener en cuenta que la operación de desplazamiento de bits se evalúa antes de la división, por lo que si desea dividir el resultado de un desplazamiento de bits, debe usar paréntesis para garantizar que la operación se realice en el orden correcto.En el segundo ejemplo,
var s = "golang.go"
es una cadena variable, por lo que la expresiónlen(s)
no es constante. Como resultado, al realizar1 << len(s) / 128
, se realiza primero la operación de división, lo que resulta enlen(s) / 128 = 0
, luego se realiza la operación de desplazamiento de bits, lo que resulta en1 << 0 = 1
, que luego se convierte al tipobyte
y se asigna aa
.En cuanto al comportamiento extraño de que
b
sea 0 cons[:]
, es más probable que se deba al hecho de ques[:]
crea una nueva sección con el mismo arreglo subyacente ques
, pero con una longitud y capacidad igual a la longitud des
. Cuando se evalúalen (s [:])
, devuelve el mismo valor quelen (s)
. Sin embargo, dado ques [:]
no es una expresión constante, la expresiónlen (s [:]) / 128
se evalúa como cero, lo que resulta en1 << 0 = 1
, que luego se convierte al tipobyte
y se asigna ab
.Se observa el mismo comportamiento al usar una cadena variable
ss
, dondelen (ss [:])
también se evalúa como cero, lo que resulta en1 << 0 = 1
, que luego se convierte al tipobyte
y se asigna aaa
ybb
.En resumen, es importante ser consciente de la diferencia entre cadenas constantes y variables al usar el operador de desplazamiento de bits u otras operaciones que dependen de la longitud de una cadena. Además, al trabajar con secciones, es importante asegurarse de que la expresión que se está evaluando sea realmente constante, de lo contrario, puede ocurrir un comportamiento inesperado.