Независимо от того, где находится рабочий каталог. Это должно быть под вашим проектом Dir. Итак, мое решение
wd, _ := os.Getwd()
for !strings.HasSuffix(wd, "<yourProjectDirName>") {
wd = filepath.Dir(wd)
}
raw, err := ioutil.ReadFile(fmt.Sprintf("%s/src/conf/conf.dev.json", wd))
Ваш путь должен всегда начинаться с вашего проекта Dir. Каждый раз, когда вы читаете файл в пакете и получаете доступ по адресу main.go или к вашему другому модулю пакета. Он всегда будет работать.
Ну, проблема в том, что переменная i
в каждой из ваших анонимных функций привязан к той же переменной вне функции.
Что вы хотите сделать, это связать переменную внутри каждой функции с отдельным неизменным значением вне функции:
var funcs = [ ]; function createfunc (i) {return function () {console.log ("My value:" + i); }; } for (var i = 0; i <3; i ++) {funcs [i] = createfunc (i); } for (var j = 0; j <3; j ++) {// и теперь давайте запустим каждый из них, чтобы увидеть funcs [j] (); }
Поскольку в JavaScript нет только области видимости - только функции - оборачивая создание функции в новую функцию, вы гарантируете, что значение «i» останется таким, как вы предполагали.
При относительно широко распространенной доступности функции Array.prototype.forEach
(в 2015 году) стоит отметить, что в тех ситуациях, когда итерация выполняется в основном по массиву значений, .forEach ( )
предоставляет чистый, естественный способ получить различное замыкание для каждой итерации. То есть, если у вас есть какой-то массив, содержащий значения (ссылки DOM, объекты и т. Д.), И возникает проблема настройки обратных вызовов, специфичных для каждого элемента, вы можете сделать это:
var someArray = [ /* whatever */ ];
// ...
someArray.forEach(function(arrayElement) {
// ... code code code for this one element
someAsynchronousFunction(arrayElement, function() {
arrayElement.doSomething();
});
});
Идея состоит в том, что каждый вызов функции обратного вызова, используемой с циклом .forEach
, будет его собственным замыканием. Параметр, передаваемый этому обработчику, является элементом массива, специфичным для данного конкретного шага итерации. Если он используется в асинхронном обратном вызове, он выиграет t сталкиваются с любыми другими обратными вызовами, установленными на других этапах итерации.
Если вы работаете в jQuery, функция $. each ()
предоставляет вам аналогичную возможность.
let
ECMAScript 6 (ES6) вводит новые ключевые слова let
и const
, которые имеют область действия, отличную от переменных на основе var
. Например, в цикле с индексом на основе let
каждая итерация цикла будет иметь новое значение i
, где каждое значение находится в пределах цикла, поэтому ваш код будет работать как вы ожидаете. Существует много ресурсов, но я бы порекомендовал блок-обзорную статью 2ality как отличный источник информации.
for (let i = 0; i < 3; i++) {
funcs[i] = function() {
console.log("My value: " + i);
};
}
Однако будьте осторожны, что IE9-IE11 и Edge до Edge 14 поддерживают , допускают
, но ошибаются в вышеприведенном (они не создают новый i
каждый раз, поэтому все вышеперечисленные функции будут регистрировать 3 как они были бы, если бы мы использовали var
). Край 14, наконец, понимает это правильно.
Другой способ сказать, что i
в ваша функция связана во время ее выполнения, а не во время ее создания.
Когда вы создаете замыкание, i
является ссылкой на переменную, определенную во внешней области, а не копия, как это было, когда вы создали закрытие. Он будет оценен во время выполнения.
Большинство других ответов предоставляют способы обхода путем создания другой переменной, которая не изменит значения для вас.
Просто подумал, что добавлю объяснение для ясности , Для решения лично я бы пошел с Харто, так как это самый очевидный способ сделать это из ответов здесь. Любой из размещенного кода будет работать, но я
Вам необходимо понять, что область видимости переменных в javascript основана на функции. Это важное отличие, чем, скажем, в c #, где у вас есть область блока, и просто сработает копирование переменной в единицу внутри for.
Заключение в функцию, которая оценивает возврат функции, такой как ответ apphacker, сделает свое дело, так как переменная теперь имеет функцию scope.
Вместо var есть также ключевое слово let, которое позволит использовать правило области видимости блока. В этом случае определение переменной внутри for сделает свое дело. Тем не менее, ключевое слово let не является практическим решением из-за совместимости.
var funcs = {}; for (var i = 0; i <3; i ++) {пусть index = i; // добавить это funcs [i] = function () {console.log ("My value:" + index); // перейти к копии}; } for (var j = 0; j <3; j ++) {funcs [j] (); }
Причина, по которой исходный пример не сработал, заключается в том, что все замыкания, созданные в цикле, ссылаются на один и тот же кадр. Фактически, имея 3 метода на одном объекте только с одной переменной i
. Они все распечатали одно и то же значение.
Попробуйте:
var funcs = []; for (var i = 0; i <3; i ++) {funcs [i] = (function (index) {return function () {console.log ("My value:" + index);};} (i)) ; } for (var j = 0; j <3; j ++) {funcs [j] (); }
Редактировать (2014):
Лично я думаю, что недавний ответ @ Aust об использовании .bind
- лучший способ сделать это сейчас. Также есть _. Частичное
lo-dash / underscore, когда вам не нужно или не хотите связываться с bind thisArg
.