Golang приведение типов

Пишу функцию, которая должна на вход принимать число Uint, удалять нечетные цифры и нули(если входящее число 0, то отдавать ответом 100), после чего, выводить измененное число в этом же формате, то есть в Uint

На данный момент код следующий:

fn := func (a uint) uint {
    if a == uint(0) { return uint(100) }
    newA := []rune(strconv.FormatUint(uint64(a), 10))
    var strA string
    for _, elem := range newA {
        if elem % 2 == 0 && elem != '0' {
            strA += string(elem)
        }
    }
    res, err := strconv.ParseUint(strA, 10, 64)
    if err != nil {
        panic(err)
    }
    a = uint(res)
    return a
}

Почему-то код не всегда отрабатывал корректно, решил проверять по действиям, наткнулся на следующую ошибку, никак не могу понять, с чем она связана. Код:

func main() {
    var num uint
    fmt.Scan(&num)
    fn := func(a uint) uint {
        if a == 0 {
            return 0
        }
        newA := []rune(strconv.FormatUint(uint64(a), 10))
        fmt.Printf("Type - %T, Num - %c\n", newA, newA)
        return 0
    }
    fn(num)
}

При входных данный 000234 в слайс рун newA записывается некорректное значение:

Output:
000234
Type - []int32, Num - [1 5 6]

Думал, какая-то ошибка в приведении string к []rune, но нет, убрав приведение типа, вывод тот же

newA := strconv.FormatUint(uint64(a), 10)
fmt.Printf("Type - %T, Num - %s\n", newA, newA)   //исправленное
Output:
000234
Type - string, Num - 156

Подскажите, почему так получается, и что можно этому противопоставить?


Ответы (2 шт):

Автор решения: Daniel Protopopov

Давайте по порядку - у вас на входе строка, в которой есть только цифры, НО строковые цифры (руны) != обычные. Вы строку читаете через fmt.Scan, здесь всё верно.

Дальше согласно описанной вами логике, вам нужно конвертировать строку в число, перед этим удалив нечетные строковые значения.

В итоге код получается следующим:

import (
    "fmt"
    "strconv"
)

func main() {
    var input = ""
    fmt.Printf("Введите данные:")
    _, errRead := fmt.Scanln(&input)
    if errRead != nil {
        fmt.Printf("Ошибка чтения данных из строки: %s", errRead.Error())
        return
    }

    value, errGetValue := GetResult(input)
    if errGetValue != nil {
        fmt.Printf("Ошибка конверсии строки в Uint: %s", errGetValue.Error())
        return
    }

    fmt.Printf("Результат: %d\n", value)
}

func GetResult(num string) (uint64, error) {
    var filteredNumbersMap = map[rune]bool{'1': false, '3': false, '5': false, '7': false, '9': false,
        '0': true, '2': true, '4': true, '6': true, '8': true}
    var cleanedUpInput []rune
    // Логика - если руна присутствует в map И её значение = true, то включать её в итоговую строку
    for _, numChar := range num {
        include, mappingExists := filteredNumbersMap[numChar]
        if mappingExists && include {
            cleanedUpInput = append(cleanedUpInput, numChar)
        }
    }
    fmt.Printf("Фильтрованный результат (строка): %s\n", string(cleanedUpInput))
    convertedResult, errParse := strconv.ParseUint(string(cleanedUpInput), 10, 64)
    // Если ошибка во время парсинга - возвращаем её
    if errParse != nil {
        return 0, errParse
    }

    if convertedResult == 0 {
        return 100, nil
    }

    return convertedResult, nil
}
→ Ссылка
Автор решения: Alexey Kucheryavenko

У вас не учтен один момент:
если длина строки равно 0. Делайте проверку на длину строки

package main

import (
    "fmt"
    "strconv"
)

func main() {
    var num uint
    fmt.Scan(&num)

    fn := func(x uint) uint {
        if x == uint(0) {
            return uint(100)
        }
        newX := []rune(strconv.FormatUint(uint64(x), 10))
        // fmt.Printf("Type - %T, Num - %v\n", newX, newX)

        var strX string

        for _, value := range newX {
            if value%2 == 0 && value != '0' && value != ' ' {
                strX = strX + string(value)
            }
        }

        // fmt.Printf("Type - %T, Num - %c\n", strX, strX)

        if len(strX) == 0 {
            return uint(100)
        }

        u64, err := strconv.ParseInt(strX, 10, 64)
        if err != nil {
            panic(err)
        }
        // fmt.Printf("Type - %T, Num - %v\n", u64, u64)

        myUint := uint(u64)
        // fmt.Printf("Type - %T, Num - %v\n", myUint, myUint)

        return myUint

    }


    // x := uint(727178)
    x := uint(num)
    fmt.Println(fn(x))
}
// ....

    if len(strX) == 0 {
        return uint(100)
    }
→ Ссылка