I am trying to transform a UTF-8 string into a Latin-1 enabled string (converting all illegal Latin-1 chars into a '?') in order to save it into a txt file to be used in a Latin-1-only system.
For test purpose I used this code:
package main
import (
"errors"
"fmt"
"os"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/transform"
)
func main() {
strUTF8 := "example 1: Г, example 2: ≤, example 3: “, etc" // utf-8 string to be converted (not Latin-1 compatible, 3 uncompatibles runes)
t := charmap.ISO8859_1.NewEncoder() // transformer to Latin-1
ini := 0 // ini establishes the initial position of the string to be analized
strISO88591 := "" // initiate Latin-1 compatible string
counter := 0 // put a counter to forcibly break after 5 iters of the loop ('for' as a 'while' is not working as expected)
err := errors.New("initiate err with non-nil value") // initiate err with non-nil value to enter the loop
for err != nil { // loop should exit for when 'err != nil' evaluates to false, that is, when err == nil
str, n, err := transform.String(t, strUTF8[ini:])
if err != nil {
ini = ini n
runes := []rune(strUTF8[ini:])
ini = ini len(string(runes[0])) //initial position of string in next iter should jump chars already converted not allowed rune
str = str "?"
}
strISO88591 = strISO88591 str
// prints to display results
fmt.Println("sISO88591:", strISO88591)
fmt.Println("err:", err)
fmt.Println("err!=nil:", err != nil)
fmt.Println()
// with the following 3 lines below it works (why not in the 'for' statement????)
//if err == nil {
// break
//}
// put a counter to forcibly break after 5 iters of the loop
counter = 1
if counter > 4 {
fmt.Println("breaking forcibly")
break
}
}
f, _ := os.Create("test.txt")
defer f.Close()
_, err = f.WriteString(strISO88591)
if err != nil {
panic(err)
}
}
That code prints in the terminal:
sISO88591: example 1: ?
err: encoding: rune not supported by encoding.
err!=nil: true
sISO88591: example 1: ?, example 2: ?
err: encoding: rune not supported by encoding.
err!=nil: true
sISO88591: example 1: ?, example 2: ?, example 3: ?
err: encoding: rune not supported by encoding.
err!=nil: true
sISO88591: example 1: ?, example 2: ?, example 3: ?, etc
err: <nil>
err!=nil: false
sISO88591: example 1: ?, example 2: ?, example 3: ?, etc, etc
err: <nil>
err!=nil: false
breaking forcibly
As we can see, after 4th iteration 'err!=nil' is evaluated to 'false' and so I expected it to exit the 'for err != nil' loop, but it never does (until I forcibly broke it with the help of a counter) . Isn´t 'for' supposed to work as other languages 'while'? Am I doing something wrong?
Specs: Go version: go1.19.5 windows/amd64
CodePudding user response:
You are redeclaring err
:
for err != nil { // This is using err declared before
str, n, err := transform.String(t, strUTF8[ini:]) // This is redeclaring and shadowing previous err
...
You can deal with it by:
for err != nil {
var str string
var n int
str, n, err = transform.String(t, strUTF8[ini:]) // This is redeclaring and shadowing previous err
...
CodePudding user response:
If you omit the loop condition it loops forever, so an infinite loop is compactly expressed. This is from a very popular tutorial for Golang, you can use structure for infinite or while loop by for command. Furthermore, the syntax for error declaration is wrong in your code.