Есть ли способ условно `fmt` строки? - PullRequest
0 голосов
/ 11 января 2020

Есть ли способ условно заполнить строку заполнителем формата в Go? Другими словами, просто игнорируйте лишние аргументы. Например:

foo := fmt.CondSprintf("foo", "bar")
// "foo" instead of "foo%!(EXTRA string=bar)"
foobar := fmt.CondSprintf("foo%s", "bar")
// "foobar"
foobar := fmt.CondSprintf("foo%s", "bar", "baz")
// "foobar"

Я могу представить что-то, что проверяет спецификатор формата c, но я пытаюсь учесть все спецификаторы формата. Такой метод, как num := fmt.CountReplacements("foo"), чтобы я мог создать большой оператор switch, тоже мог бы работать.

Ответы [ 2 ]

0 голосов
/ 11 января 2020

Предисловие: Я выпустил эту утилиту в github.com/icza/gox, см. fmtx.CondSprintf().


Как уже отмечалось, пакет fmt сообщает об этом, потому что это ошибка в вашем коде, это ошибка в том, как вы называете fmt.Sprintf().

Так что рекомендуется вычислить выясните, почему строка формата и переданные аргументы не совпадают, и исправьте этот код.

Но чтобы ответить на ваш вопрос: стандартная библиотека lib (в частности, пакет fmt) не позволяет игнорировать дополнительные аргументы .

Но этого можно достичь. Ключ должен использовать явные индексы аргументов , подробнее об этом: Заменить все переменные в Sprintf одной и той же переменной .

Поэтому, когда используются явные индексы аргументов, вы говорите в строке формата, какой аргумент вы хотите использовать. И если при использовании индексов аргументов вы пропускаете некоторые аргументы, это не сообщается как ошибка.

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

Итак, для достижения желаемого: добавьте дополнительный пустой аргумент, это может быть пустая строка "". И расширите строку формата глаголом %[n]s, где n - количество новых аргументов (количество старых аргументов плюс 1).

И вызовите fmt.Sprintf() со строкой нового формата и расширенным списком аргументов. .

Без лишних слов, вот оно:

func CondSprintf(format string, v ...interface{}) string {
    v = append(v, "")
    format += fmt.Sprint("%[", len(v), "]s")
    return fmt.Sprintf(format, v...)
}

Тестирование:

fmt.Println(CondSprintf("foo", "bar"))
fmt.Println(CondSprintf("foo%s", "bar"))
fmt.Println(CondSprintf("foo%s", "bar", "baz"))

Вывод:

foo
foobar
foobar

Обратите внимание, что если fmt.Sprintf() был бы использован вместо этого CondSprintf(), результат был бы следующим:

foo%!(EXTRA string=bar)
foobar
foobar%!(EXTRA string=baz)

Попробуйте примеры на Go Playground .

0 голосов
/ 11 января 2020

Попробуйте:

func CondSprintf(f string, args ...interface{}) string {
    n := strings.Count(f, "%s")
    if n < len(args) {
        args = args[:n]
    }
    return fmt.Sprintf(f, args...)
}

Вы можете запустить это на детской площадке .

Как говорит Бурак в комментарии, это не будет хорошей идеей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...