Home > database >  Using Go 'for' loop as 'while'
Using Go 'for' loop as 'while'

Time:02-03

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.

  • Related