странное поведение при той же переменной, что и вход и выход функции - PullRequest
0 голосов
/ 28 апреля 2018

Для следующего кода, кажется, идет в тупик. После s, err := minusOne(s) s сокращается в соответствии с информацией журнала. Но журнал минус до показывает, что он никогда не менялся.

func minusOne(s string) (string, error) {
    if len(s) >= 0 {
        return s[1:], nil
    }
    return "", nil
}

func TestStr(t *testing.T) {
    s := "hello world"
    for {
        log.Println("before minus", s)
        s, err := minusOne(s)
        log.Println("after minus", s)
        if err == nil && len(s) == 0 {
            break
        }
    }
}

Если я слегка изменю его, он будет работать, как и ожидалось.

s1, err := minusOne(s)
s = s1

Или, если я уберу ошибку, возвращающуюся в функции minusOne, и это тоже сработает.

s = minusOne(s)

Я действительно не могу этого понять. Кто-нибудь может помочь с этим?

Ответы [ 3 ]

0 голосов
/ 28 апреля 2018

На каждой итерации вы объявляете новые переменные с именами s и err:

s, err := minusOne(s)

Их область действия - только текущая итерация, поэтому в приведенной выше строке используется та же самая переменная s, объявленная вне цикла. От Декларации и область действия часть спецификации Go:

Go имеет лексическую область видимости, используя блоки:

  1. Область действия идентификатора константы или переменной, объявленного внутри функции, начинается в конце ConstSpec или VarSpec (ShortVarDecl для коротких объявлений переменных) и заканчивается в конце самого внутреннего содержащего блока.

Чтобы исправить это, нужно использовать назначение:

var err error
for {
    // ...
    s, err = minusOne(s)
    // ...
}
0 голосов
/ 28 апреля 2018

Вы используете краткое объявление var :=. Вы должны позаботиться об этом.

Внутри цикла for вы создаете две новые переменные err, но также s (с новой областью видимости внутри цикла for). Это не будет проблемой, если вы делаете это в той же области.

Вы можете просто извлечь err в предварительно объявленную переменную, перед тем как вот так:

var err error
s, err = minusOne(s)
0 голосов
/ 28 апреля 2018

не используйте s в цикле for,: = добавит новую локальную переменную. просто переименуйте s для добычи в s1. Вы также можете объявить внешний цикл for и заменить: = на =

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