0

In C, We define the character of a string as Char. So I want to change a character of a string in Go.

if sum%11 != int(str[strlen-1]) {
    str[strlen-1] = byte(sum % 11)
    //fmt.Printf("%T %T\n", str[strlen-1], byte(sum%11))
} else {
    fmt.Println(sum)
}

But it will report an error "cannot assign to str[strlen - 1]". Both str[strlen-1] and byte(sum%11) are uint8. Why is it wrong? How should I convert?

1
  • 1
    Strings are immutable, but slices are not. If you are dealing with binary data convert the string to []byte or []uint8 first. If you are dealing with UTF-8 encoded text convert to []rune (rune is an alias for uint32). If you're dealing with any other text encoding you're on your own. Commented Sep 19, 2019 at 6:48

2 Answers 2

1

Unlike in C, Go strings are immutable, so you cannot modify individual bytes in a string. However, you can convert the string to a byte array, change that, and convert that byte array to string.

arr:=[]byte(str)
arr[strlen-1]=byte(sum%11)
str=string(arr)

Note that Go strings are UTF-8 encoded. A rune may be represented as multiple bytes. By modifying strings like this you may end up with an invalid string.

Sign up to request clarification or add additional context in comments.

6 Comments

Yes, but the are still byte arrays.
UTF-8 is a variable-length encoding with one to four bytes per character. A byte is not a character.
If the underlying string uses 1-byte runes, then you can treat the string as a byte array, can you not?
Yes, the pedantic solution is go by last rune (1-4 bytes) and replace the rune with a 1 byte. But since the OP referenced C & most likely an ASCII string, this solution is probably fine.
An 8-bit Unicode codepoint is UTF-8 encoded as one or two bytes.
|
0

In general, you should do it this way:

s := "some UTF8® string"
r := []rune(s)
fmt.Println("The last character is", r[len(r)-1])
result := string(r)
// Output: g

In your case I am not sure what you mean by a "sum" variable. Let's assume the sum is int and want to compare the end of the string with it. The issue here is that %11 could be a two digits string (10) also:

str := "anyUTF8®string9"
sum := 10
remainderDevision := strconv.Itoa(sum % 11) // It is "10"

rInput := []rune(str)
rDivision := []rune(remainderDevision)

// Compare the last 1 or two characters:
if string(rInput[len(rInput)-len(rDivision):]) != string(rDivision) {
    fmt.Println(string(rInput[len(rInput)-len(rDivision):])) // Output: g9

    if len(rDivision) > 1 {
        secondCharFromEnd := rInput[len(rInput)-2]
        _, errNotInt := strconv.Atoi(string(secondCharFromEnd))
        if errNotInt != nil {
            // Replace only the last char with two new chars
            rInput[len(rInput)-1] = rDivision[0]
            rInput = append(rInput, rDivision[1])
        } else {
            // Replace the last 2 chars
            rInput[len(rInput)-2] = rDivision[0]
            rInput[len(rInput)-1] = rDivision[1]
        }
    } else {
        // Just replace the last char with it
        rInput[len(rInput)-1] = rDivision[0]
    }
}
fmt.Println("Result:", string(rInput))
// Output: anyUTF8®string10

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.